import { JSFuncs, Boards } from 'mixly';
import * as Blockly from 'blockly/core';

/********************************************
    OUTPUT - 输出模块
*********************************************/
// OUTPUT Digital 数字输出型模块：食人鱼LED、有源蜂鸣器Buzzer active、风扇、震动电机、继电器
export const yf_output_digital = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC);
    generator.setups_['setup_output_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', OUTPUT);';
    var code = 'digitalWrite(' + dropdown_pin + ',' + dropdown_stat + ');\n'
    return code;
}

// OUTPUT PWM：食人鱼LED、风扇、震动电机
export const yf_output_pwm = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var value_num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC);
    generator.setups_['setup_output_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', OUTPUT);';
    var code = 'analogWrite(' + dropdown_pin + ',' + value_num + ');\n'
    return code;
}

// Buzzer Passive
export const yf_buzzer_speaker_frequency = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var fre = generator.valueToCode(this, 'FREQUENCY', generator.ORDER_ASSIGNMENT) || '0';
    generator.setups_['setup_output_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', OUTPUT);';
    var code = "tone(" + dropdown_pin + "," + fre + ");\n";
    return code;
}

// Buzzer Passive
export const yf_buzzer_speaker_frequency_duration = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var fre = generator.valueToCode(this, 'FREQUENCY', generator.ORDER_ASSIGNMENT) || '0';
    var dur = generator.valueToCode(this, 'DURATION', generator.ORDER_ASSIGNMENT) || '0';
    generator.setups_['setup_output_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', OUTPUT);';
    var code = "tone(" + dropdown_pin + "," + fre + "," + dur + ");\n";
    return code;
}

// Notone 结束声音
export const yf_notone = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var code = '';
    if (window.isNaN(dropdown_pin)) {
        code = code + 'pinMode(' + dropdown_pin + ', OUTPUT);\n';
    } else {
        generator.setups_['setup_output_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', OUTPUT);';
    }
    code += "noTone(" + dropdown_pin + ");\n";
    return code;
}

// 红绿灯 交通信号指示灯
export const yf_trafficSignal = function (_, generator) {
    var P1 = generator.valueToCode(this, 'PIN1', generator.ORDER_ATOMIC || '10');
    var P2 = generator.valueToCode(this, 'PIN2', generator.ORDER_ATOMIC || '11');
    generator.setups_['setup_output_' + P1] = 'pinMode(' + P1 + ', OUTPUT);';
    generator.setups_['setup_output_' + P2] = 'pinMode(' + P2 + ', OUTPUT);';
    var what = this.getFieldValue('WHAT');
    var code = '';
    if (what == 'RLED') {
        code += 'digitalWrite(' + P1 + ', LOW);\n';
        code += 'digitalWrite(' + P2 + ', HIGH);\n';
    } else if (what == 'YLED') {
        code += 'digitalWrite(' + P1 + ', HIGH);\n';
        code += 'digitalWrite(' + P2 + ', LOW);\n';
    } else if (what == 'GLED') {
        code += 'digitalWrite(' + P1 + ', HIGH);\n';
        code += 'digitalWrite(' + P2 + ', HIGH);\n';
    } else if (what == 'OFFLED') {
        code += 'digitalWrite(' + P1 + ', LOW);\n';
        code += 'digitalWrite(' + P2 + ', LOW);\n';
    }
    return code;
}

// OTP 固定语音播报 获取列表值
export const yf_otpVoiceBroadcast_list1 = function (_, generator) {
    var code = this.getFieldValue('VAR');
    return [code, generator.ORDER_ATOMIC];
}

// OTP 固定语音播报 获取列表值2
export const yf_otpVoiceBroadcast_list2 = yf_otpVoiceBroadcast_list1;

// OTP 固定语音播报 静音码 后接数字表示时长 单位10ms
export const yf_otpVoiceBroadcast_muteCode = yf_otpVoiceBroadcast_list1;

// OTP 固定语音播报
export const yf_otpVoiceBroadcast_play = function (_, generator) {
    var play_pin = generator.valueToCode(this, 'PLAYPIN', generator.ORDER_ATOMIC) || '6';
    var what = generator.valueToCode(this, 'VOICENUMBER', generator.ORDER_ATOMIC) || '0';

    var funcName = 'yfOTPSendDataNoStartCode';
    var funcCode = 'void ' + funcName + '(int otppin, int addr) {\n'
        + '  for (int i = 0; i < 8; i++) {\n'
        + '    digitalWrite(otppin, HIGH);\n'
        + '    if (addr & 1) {\n'
        + '      delayMicroseconds(2400); // >2400us\n'
        + '      digitalWrite(otppin, LOW);\n'
        + '      delayMicroseconds(800);  // >800us\n'
        + '    } else {\n'
        + '      delayMicroseconds(800);  // >800us\n'
        + '      digitalWrite(otppin, LOW);\n'
        + '      delayMicroseconds(2400); // >2400us\n'
        + '    }\n'
        + '    addr >>= 1;\n'
        + '  }\n'
        + '  digitalWrite(otppin, HIGH);\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;

    var funcName2 = 'yfOTPSendData';
    var funcCode2 = 'void ' + funcName2 + '(int otppin, int addr) {\n'
        + '  digitalWrite(otppin, LOW);\n'
        + '  delay(3);           // >2ms\n'
        + '  ' + funcName + '(otppin, addr);\n'
        + '}\n';
    generator.definitions_[funcName2] = funcCode2;

    generator.setups_['setup_output_' + play_pin] = 'pinMode(' + play_pin + ', OUTPUT);';
    generator.setups_['setup_output_init_HIGH' + play_pin] = 'digitalWrite(' + play_pin + ', HIGH); // 引脚至高电平，初始化';

    var code = funcName2 + '(' + play_pin + ',' + what + ');\n';
    return code;
}

// OTP 固定语音播报 功能设置 - 音量、播放循环停止
export const yf_otpVoiceBroadcast_set = function (_, generator) {
    var play_pin = generator.valueToCode(this, 'PLAYPIN', generator.ORDER_ATOMIC) || '6';
    var varValue = this.getFieldValue('VAR');

    var funcName = 'yfOTPSendDataNoStartCode';
    var funcCode = 'void ' + funcName + '(int otppin, int addr) {\n'
        + '  for (int i = 0; i < 8; i++) {\n'
        + '    digitalWrite(otppin, HIGH);\n'
        + '    if (addr & 1) {\n'
        + '      delayMicroseconds(2400); // >2400us\n'
        + '      digitalWrite(otppin, LOW);\n'
        + '      delayMicroseconds(800);  // >800us\n'
        + '    } else {\n'
        + '      delayMicroseconds(800);  // >800us\n'
        + '      digitalWrite(otppin, LOW);\n'
        + '      delayMicroseconds(2400); // >2400us\n'
        + '    }\n'
        + '    addr >>= 1;\n'
        + '  }\n'
        + '  digitalWrite(otppin, HIGH);\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;

    var funcName2 = 'yfOTPSendData';
    var funcCode2 = 'void ' + funcName2 + '(int otppin, int addr) {\n'
        + '  digitalWrite(otppin, LOW);\n'
        + '  delay(3);           // >2ms\n'
        + '  ' + funcName + '(otppin, addr);\n'
        + '}\n';
    generator.definitions_[funcName2] = funcCode2;

    generator.setups_['setup_output_' + play_pin] = 'pinMode(' + play_pin + ', OUTPUT);';
    generator.setups_['setup_output_init_HIGH' + play_pin] = 'digitalWrite(' + play_pin + ', HIGH); // 引脚至高电平，初始化';

    var code = funcName2 + '(' + play_pin + ',' + varValue + ');\n';
    return code;
}

// OTP 固定语音播报 连码播放
export const yf_otpVoiceBroadcast_cplay = function (_, generator) {
    var play_pin = generator.valueToCode(this, 'PLAYPIN', generator.ORDER_ATOMIC) || '6';
    var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
    // var size = generator.valueToCode(this, 'WHATFUNSIZE', generator.ORDER_ATOMIC) || '2';

    var funcName = 'yfOTPSendDataNoStartCode';
    var funcCode = 'void ' + funcName + '(int otppin, int addr) {\n'
        + '  for (int i = 0; i < 8; i++) {\n'
        + '    digitalWrite(otppin, HIGH);\n'
        + '    if (addr & 1) {\n'
        + '      delayMicroseconds(2400); // >2400us\n'
        + '      digitalWrite(otppin, LOW);\n'
        + '      delayMicroseconds(800);  // >800us\n'
        + '    } else {\n'
        + '      delayMicroseconds(800);  // >800us\n'
        + '      digitalWrite(otppin, LOW);\n'
        + '      delayMicroseconds(2400); // >2400us\n'
        + '    }\n'
        + '    addr >>= 1;\n'
        + '  }\n'
        + '  digitalWrite(otppin, HIGH);\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;

    var funcName2 = 'yfOTPSendData';
    var funcCode2 = 'void ' + funcName2 + '(int otppin, int addr) {\n'
        + '  digitalWrite(otppin, LOW);\n'
        + '  delay(3);           // >2ms\n'
        + '  ' + funcName + '(otppin, addr);\n'
        + '}\n';
    generator.definitions_[funcName2] = funcCode2;

    var funcName3 = 'yfOTPCPlay';
    var funcCode3 = 'void ' + funcName3 + '(int otppin, int serial_number[], int sizes) {\n'
        + '  int checksum = 0;\n'
        + '  ' + funcName2 + '(otppin, 0xf1); // 头码\n'
        + '  checksum += 0xf1;\n'
        + '  for (int index = 0; index < sizes; index++) {\n'
        + '    ' + funcName + '(otppin, serial_number[index]); // 语音列表码\n'
        + '    checksum += serial_number[index];\n'
        + '  }\n'
        + '  ' + funcName + '(otppin, 0xF3); // 尾码\n'
        + '  checksum += 0xF3;\n'
        + '  ' + funcName + '(otppin, checksum & 0xFF); // 校验和\n'
        + '}\n';
    generator.definitions_[funcName3] = funcCode3;

    generator.setups_['setup_output_' + play_pin] = 'pinMode(' + play_pin + ', OUTPUT);';
    generator.setups_['setup_output_init_HIGH' + play_pin] = 'digitalWrite(' + play_pin + ', HIGH); // 引脚至高电平，初始化';

    var code = funcName3 + '(' + play_pin + ',' + varName + ',sizeof(' + varName + ')/sizeof(' + varName + '[0]));\n';
    return code;
}

//MP3音频播放模块 获取功能列表
export const yf_mp3AudioPlayModuleGetFunWithNumber = function (_, generator) {
    var code = this.getFieldValue('VAR');
    return [code, generator.ORDER_ATOMIC];
}

//MP3音频播放模块 配合数字功能 - 选曲播放/插播，设置音量（0~30），设置EQ模式（0~4），播放模式（0~7）
export const yf_mp3AudioPlayModuleSetFunWithNum = function (_, generator) {
    var play_pin = generator.valueToCode(this, 'PLAYPIN', generator.ORDER_ATOMIC) || '6';
    var varValue = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '0';
    var serialNumber = generator.valueToCode(this, 'NUMBER', generator.ORDER_ATOMIC) || '0';

    var funcName = 'yfMP3MoudleSendData';
    var funcCode = 'void ' + funcName + '(int mp3playpin, int addr) {\n'
        + '  digitalWrite(mp3playpin, HIGH);\n'
        + '  delay(1);           // >1ms\n'
        + '  digitalWrite(mp3playpin, LOW);\n'
        + '  delay(10);           // >3ms\n'
        + '  for (int i = 0; i < 8; i++) {\n'
        + '    digitalWrite(mp3playpin, HIGH);\n'
        + '    if (addr & 1) {\n'
        + '      delayMicroseconds(2400); // >1200us\n'
        + '      digitalWrite(mp3playpin, LOW);\n'
        + '      delayMicroseconds(800);  // >400us\n'
        + '    } else {\n'
        + '      delayMicroseconds(800);  // >400us\n'
        + '      digitalWrite(mp3playpin, LOW);\n'
        + '      delayMicroseconds(2400); // >1200us\n'
        + '    }\n'
        + '    addr >>= 1;\n'
        + '  }\n'
        + '  digitalWrite(mp3playpin, HIGH);\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;

    var funcName2 = 'yfMP3MoudleFunSetWithNum';
    var funcCode2 = 'void ' + funcName2 + '(int mp3playpin, int fun, int addrnum) {\n'
        + '  int addrnumArray[5] = {0};\n'
        + '  int addrnumArraySize = 0;\n'
        + '  int num = addrnum;\n'
        + '  while (num > 0) { // 数字转换数据\n'
        + '    addrnumArray[addrnumArraySize] = (num % 10);\n'
        + '    num = int(num / 10);\n'
        + '    addrnumArraySize++;\n'
        + '  }\n'
        + '  for (int k = addrnumArraySize - 1; k >= 0; k--) { // 倒序发送数字指令\n'
        + '    ' + funcName + '(mp3playpin, addrnumArray[k]);\n'
        + '  }\n'
        + '  ' + funcName + '(mp3playpin, fun);  // 发送功能指令\n'
        + '}\n';
    generator.definitions_[funcName2] = funcCode2;

    generator.setups_['setup_output_' + play_pin] = 'pinMode(' + play_pin + ', OUTPUT);';

    var code = funcName2 + '(' + play_pin + ',' + varValue + ',' + serialNumber + ');\n';
    return code;
}

//MP3音频播放模块 获取功能列表
export const yf_mp3AudioPlayModuleGetFun = yf_mp3AudioPlayModuleGetFunWithNumber;

//MP3音频播放模块 - 播放，暂停，停止，上一曲，下一曲，上一目录，下一目录，清除已发送数字，停止插播, 系统睡眠
export const yf_mp3AudioPlayModuleSetFun = function (_, generator) {
    var play_pin = generator.valueToCode(this, 'PLAYPIN', generator.ORDER_ATOMIC) || '6';
    var varValue = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '0';

    var funcName = 'yfMP3MoudleSendData';
    var funcCode = 'void ' + funcName + '(int mp3playpin, int addr) {\n'
        + '  digitalWrite(mp3playpin, HIGH);\n'
        + '  delay(1);           // >1ms\n'
        + '  digitalWrite(mp3playpin, LOW);\n'
        + '  delay(10);           // >3ms\n'
        + '  for (int i = 0; i < 8; i++) {\n'
        + '    digitalWrite(mp3playpin, HIGH);\n'
        + '    if (addr & 1) {\n'
        + '      delayMicroseconds(2400); // >1200us\n'
        + '      digitalWrite(mp3playpin, LOW);\n'
        + '      delayMicroseconds(800);  // >400us\n'
        + '    } else {\n'
        + '      delayMicroseconds(800);  // >400us\n'
        + '      digitalWrite(mp3playpin, LOW);\n'
        + '      delayMicroseconds(2400); // >1200us\n'
        + '    }\n'
        + '    addr >>= 1;\n'
        + '  }\n'
        + '  digitalWrite(mp3playpin, HIGH);\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;

    generator.setups_['setup_output_' + play_pin] = 'pinMode(' + play_pin + ', OUTPUT);';

    var code = funcName + '(' + play_pin + ',' + varValue + ');\n';
    return code;
}

//录放模块 - 播放一次录音，循环播放录音（断电停止）；使能/禁用 喇叭
export const yf_voiceRecorderModuleSetFun = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PLAYPIN', generator.ORDER_ATOMIC);
    var what = this.getFieldValue('VAR');

    generator.setups_['setup_output_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', OUTPUT);';

    var code = '';
    if (what == '1') {
        code += 'digitalWrite(' + dropdown_pin + ', LOW);\n';
        code += 'delayMicroseconds(2); // 2us \n';
        code += 'digitalWrite(' + dropdown_pin + ', HIGH);\n';
        code += 'delay(50); // > 30ms \n';
        code += 'digitalWrite(' + dropdown_pin + ', LOW);\n';
    } else if (what == '2') {
        code += 'digitalWrite(' + dropdown_pin + ', LOW);\n';
        code += 'delayMicroseconds(2); // 2us \n';
        code += 'digitalWrite(' + dropdown_pin + ', HIGH);\n';
        code += 'delay(2050); // > 2s \n';
        code += 'digitalWrite(' + dropdown_pin + ', LOW);\n';
    } else if (what == '3') {
        code += 'digitalWrite(' + dropdown_pin + ', LOW);\n';
    } else if (what == '4') {
        code += 'digitalWrite(' + dropdown_pin + ', HIGH);\n';
    }
    return code;
}

//语音合成模块 TTS初始化
export const yf_voiceTTSModuleBegin = function (_, generator) {
    var ttsrxpin = generator.valueToCode(this, 'TTSRXPIN', generator.ORDER_ATOMIC);
    var ttstxpin = generator.valueToCode(this, 'TTSTXPIN', generator.ORDER_ATOMIC);
    generator.definitions_['include_YFTTS'] = '#include <YFTTS.h>';
    var board_type = Boards.getType();  // 获取板型
    if (board_type == "arduino_esp32" || board_type == "arduino_esp32s3" || board_type == "arduino_esp32c3") {
        generator.definitions_['object_YFTTS'] = 'YFTTS YF_TTS(&Serial2);  // 绑定串口Serial2, 默认引脚RX在GPIO16, TX在GPIO17';
        generator.setups_['setup_TTS_Begin'] = 'YF_TTS.begin(115200, -1, '+ ttstxpin +');  // 初始化TTS，默认波特率115200, 主板TX引脚25，请注意初始化需要500ms左右\n';
    } else if(board_type == "arduino_avr"){
        generator.definitions_['include_SoftwareSerial'] = '#include <SoftwareSerial.h>';
        generator.definitions_['object_YFTTS'] = 'SoftwareSerial mySerial('+ ttsrxpin +', '+ ttstxpin +');  // 主板RX(随便配置无用), TX, ; \nYFTTS YF_TTS(mySerial);';
        generator.setups_['setup_TTS_Begin'] = 'YF_TTS.begin(115200);\n';
    }
    return "";
}

//语音合成模块 TTS设置
export const yf_voiceTTSModuleSet = function () {
    var what_PRONOUNCER = this.getFieldValue('PRONOUNCER');
    var what_VOLUME = this.getFieldValue('VOLUME');
    var what_SPEECH_RATE = this.getFieldValue('SPEECH_RATE');
    var what_TONE = this.getFieldValue('TONE');

    var code = '';
    code += 'YF_TTS.setTTSParameters(\'m\','+ what_PRONOUNCER +');\n';
    code += 'YF_TTS.setTTSParameters(\'s\','+ what_SPEECH_RATE +');\n';
    code += 'YF_TTS.setTTSParameters(\'t\','+ what_TONE +');\n';
    code += 'YF_TTS.setTTSParameters(\'v\','+ what_VOLUME +');\n';
    return code;
}

//语音合成模块 TTS 播放字符串，适配变量
export const yf_voiceTTSModulePlay  = function (_, generator) {
    // var inputVariable = this.getFieldValue('STR');
    var inputVariable = generator.valueToCode(this, 'INPUTSTR', generator.ORDER_ATOMIC) || '0';

    var code = '';
    code += 'YF_TTS.speak('+ inputVariable +');\n';
    return code;
}

//语音合成模块 TTS 播放铃声
export const yf_voiceTTSModulePlayRing = function () {
    var what_Ring = this.getFieldValue('RING');

    var code = '';
    code += 'YF_TTS.speak("'+ what_Ring +'");\n';
    return code;
}


/* INPUT DIGITAL - 数字输入型模块：
    按钮模块、磁控开关、角度传感器、红外感应器、震动传感器、
    热释电传感器、触摸传感器、碰撞检测开关、寻迹模块、旋转编码器
*/
export const yf_input_digital = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    generator.setups_['setup_input_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', INPUT);';
    var code = 'digitalRead(' + dropdown_pin + ')';
    return [code, generator.ORDER_ATOMIC];
}

/* INPUT ANALOG - 模拟输入型模块：
    电位器模块、环境光传感器、声音传感器、土壤湿度检测、摇杆XY轴
*/
export const yf_input_analog = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    //generator.setups_['setup_input_'+dropdown_pin] = 'pinMode('+dropdown_pin+', INPUT);';
    var code = 'analogRead(' + dropdown_pin + ')';
    return [code, generator.ORDER_ATOMIC];
}

// Temperature-lm35
export const yf_temperature = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var code = 'analogRead(' + dropdown_pin + ') * 0.488';
    return [code, generator.ORDER_ATOMIC];
}

// DHT11 22
export const yf_dht = function (_, generator) {
    var sensor_type = this.getFieldValue('TYPE');
    var dropdown_pin = this.getFieldValue('PIN');
    var what = this.getFieldValue('WHAT');
    generator.definitions_['include_DHT'] = '#include <DHT.h>';
    generator.definitions_['var_declare_dht' + dropdown_pin] = 'DHT YFDHT' + dropdown_pin + '(' + dropdown_pin + ',' + sensor_type + ')' + ';';
    generator.setups_['DHT_SETUP' + dropdown_pin] = 'YFDHT' + dropdown_pin + '.begin();';
    var code = 'YFDHT' + dropdown_pin + '.read' + what + '()';
    return [code, generator.ORDER_ATOMIC];
}

// Ultrasonic 超声波 SR04
export const yf_ultrasonic_04 = function (_, generator) {
    var dropdown_pin1 = generator.valueToCode(this, 'PINT', generator.ORDER_ATOMIC);
    var dropdown_pin2 = generator.valueToCode(this, 'PINE', generator.ORDER_ATOMIC);
    generator.setups_['setup_output_' + dropdown_pin1] = 'pinMode(' + dropdown_pin1 + ', OUTPUT);';
    generator.setups_['setup_output_' + dropdown_pin2] = 'pinMode(' + dropdown_pin2 + ', INPUT);';
    var funcName = 'checkdistance_' + dropdown_pin1 + '_' + dropdown_pin2;
    var code = 'float' + ' ' + funcName + '() {\n'
        + '  digitalWrite(' + dropdown_pin1 + ', LOW);\n'
        + '  delayMicroseconds(2);\n'
        + '  digitalWrite(' + dropdown_pin1 + ', HIGH);\n'
        + '  delayMicroseconds(10);\n'
        + '  digitalWrite(' + dropdown_pin1 + ', LOW);\n'
        + '  float distance = pulseIn(' + dropdown_pin2 + ', HIGH) / 58.00;\n'
        + '  delay(10);\n'
        + '  return distance;\n'
        + '}\n';
    generator.definitions_[funcName] = code;
    return [funcName + '()', generator.ORDER_ATOMIC];
}

// VC 离线语音识别模块 硬件串口
export const yf_vcSpeechRecognition_Hardware = function (_, generator) {
    var board_type = Boards.getType();  // 获取板型
    var baud = this.getFieldValue('BAUD');
    var serial_select;
    if (board_type == "arduino_esp32" || board_type == "arduino_esp32s3" || board_type == "arduino_esp32c3") {
        serial_select = this.getFieldValue('serial_select');
    } else {
        serial_select = this.getFieldValue('serial_select');
        generator.setups_['setup_serial_' + serial_select] = serial_select + '.begin(' + baud + ');';
    }
    var funcName = 'serialReceiveData';
    var code = 'uint8_t' + ' ' + funcName + '() {\n' +
        '  uint8_t c;\n' +
        '  static uint8_t inBuf[3];   //数据数组\n' + // static 必须有，在测试ESPONE 主板时，没有无法正常工作
        '  static uint8_t offset;\n' +
        '  static uint32_t checksum;\n' +
        '  static enum _serial_state { IDLE, HEADER_5A } c_state;\n\n' +
        '  while (' + serial_select + '.available()) {\n' +
        '    c = ' + serial_select + '.read();     // 读串口缓冲区\n' +
        '    if (c_state == IDLE) {        // 串口状态空闲,等待 HEADER 5A 状态的到来\n' +
        '      if (c == 0x5A) {            // 判断是否进入 HEADER 5A\n' +
        '        checksum = c;             // 校验和 1  -  head\n' +
        '        c_state = HEADER_5A;      // 进入 HEADER_5A 状态\n' +
        '        offset = 0;\n' +
        '      } else  c_state = IDLE;     // 返回IDLE状态\n' +
        '    } else if (c_state == HEADER_5A && offset < 3) {\n' +
        '      checksum += c;              // 校验和 2  -  data\n' +
        '      inBuf[offset] = c;\n' +
        '      offset++;\n' +
        '    } else if (c_state == HEADER_5A && offset >= 3) {\n' +
        '      c_state = IDLE;             // 返回IDLE状态\n' +
        '      if ((checksum & 0xFF) == c) {\n' +
        '        return inBuf[0];          // 返回指令值\n' +
        '      }\n' +
        '    }\n' +
        '  }\n' +
        '  return 0x01;                    // 未接收数据，默认返回0x01\n' +
        '}\n';
    generator.definitions_[funcName] = code;
    return [funcName + '()', generator.ORDER_ATOMIC];
}

// VC 离线语音识别模块 软件串口
export const yf_vcSpeechRecognition_Software = function (_, generator) {
    var board_type = Boards.getType();  // 获取板型
    var dropdown_pin_rx = generator.valueToCode(this, 'PINRX', generator.ORDER_ATOMIC);
    var dropdown_pin_tx = generator.valueToCode(this, 'PINTX', generator.ORDER_ATOMIC);
    var baud = this.getFieldValue('BAUD');
    var code = '';
    if (board_type == "arduino_esp32" || board_type == "arduino_esp32s3" || board_type == "arduino_esp32c3") {
        code = "not support";
        return code;
    }
    generator.definitions_['include_SoftwareSerial'] = '#include <SoftwareSerial.h>';
    generator.definitions_['var_declare_' + dropdown_pin_rx + '_' + dropdown_pin_tx] = 'SoftwareSerial ' + 'yfSerial' + dropdown_pin_rx + '_' + dropdown_pin_tx + '(' + dropdown_pin_rx + ',' + dropdown_pin_tx + '); // RX,TX';
    generator.setups_['setup_serial_yfSerial_' + dropdown_pin_rx + '_' + dropdown_pin_tx] = 'yfSerial' + dropdown_pin_rx + '_' + dropdown_pin_tx + '.begin(' + baud + ');';

    var funcName = 'serialReceiveData';
    code = 'uint8_t' + ' ' + funcName + '() {\n' +
        '  uint8_t c;\n' +
        '  static uint8_t inBuf[3];   //数据数组\n' + // static 必须有，在测试ESPONE 主板时，没有无法正常工作
        '  static uint8_t offset;\n' +
        '  static uint32_t checksum;\n' +
        '  static enum _serial_state { IDLE, HEADER_5A } c_state;\n\n' +
        '  while (' + 'yfSerial' + dropdown_pin_rx + '_' + dropdown_pin_tx + '.available()) {\n' +
        '    c = ' + 'yfSerial' + dropdown_pin_rx + '_' + dropdown_pin_tx + '.read();     // 读串口缓冲区\n' +
        '    if (c_state == IDLE) {        // 串口状态空闲,等待 HEADER 5A 状态的到来\n' +
        '      if (c == 0x5A) {            // 判断是否进入 HEADER 5A\n' +
        '        checksum = c;             // 校验和 1  -  head\n' +
        '        c_state = HEADER_5A;      // 进入 HEADER_5A 状态\n' +
        '        offset = 0;\n' +
        '      } else  c_state = IDLE;     // 返回IDLE状态\n' +
        '    } else if (c_state == HEADER_5A && offset < 3) {\n' +
        '      checksum += c;              // 校验和 2  -  data\n' +
        '      inBuf[offset] = c;\n' +
        '      offset++;\n' +
        '    } else if (c_state == HEADER_5A && offset >= 3) {\n' +
        '      c_state = IDLE;             // 返回IDLE状态\n' +
        '      if ((checksum & 0xFF) == c) {\n' +
        '        return inBuf[0];          // 返回指令值\n' +
        '      }\n' +
        '    }\n' +
        '  }\n' +
        '  return 0x01;                    // 未接收数据，默认返回0x01\n' +
        '}\n';
    generator.definitions_[funcName] = code;

    return [funcName + '()', generator.ORDER_ATOMIC];

}

/* OLD VERSION BLUE BOARD - INPUT DIGITAL - 蓝板 数字输入型模块：
    光敏传感器、声音传感器、火焰传感器、霍尔传感器、TCRT5000传感器、
    土壤湿度数字型传感器、U型光电开关、摇杆按钮
*/
export const yf_input_digital_blue_board = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    generator.setups_['setup_input_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', INPUT);';
    var code = 'digitalRead(' + dropdown_pin + ')';
    return [code, generator.ORDER_ATOMIC];
}

/********************************************
SENSOR - 传感器模块
循迹传感器-QTR-5RC
*********************************************/

// 手势传感器APDS9960 - 初始化并使能特定传感器
export const yf_apds9960_init = function (_, generator) {
    var sensor_type = this.getFieldValue('SEN');
    generator.definitions_['include_Wire'] = '#include <Wire.h>';
    generator.definitions_['include_apds9960'] = '#include "YFSparkFun_APDS9960.h"';
    generator.definitions_['var_apds9960'] = 'SparkFun_APDS9960 apds = SparkFun_APDS9960();';
    generator.setups_['setup_init_apds9960'] = 'apds.init();\n';
    var code = 'apds.' + sensor_type + '(true)';
    return [code, generator.ORDER_ATOMIC];
}
// 手势传感器APDS9960 - 手势功能可用
export const yf_apds9960_gesture_available = function (_, generator) {
    var code = 'apds.isGestureAvailable()';
    return [code, generator.ORDER_ATOMIC];
}
// 手势传感器APDS9960 - 读取手势
export const yf_apds9960_read_gesture = function (_, generator) {
    var code = 'apds.readGesture()';
    return [code, generator.ORDER_ATOMIC];
}
// 手势传感器APDS9960 - 手势名
export const yf_apds9960_gesture_name = function (_, generator) {
    var gesture_name = this.getFieldValue('GESNAME');
    var code = gesture_name;
    return [code, generator.ORDER_ATOMIC];
}

// 颜色传感器TCS34725 - 初始化并读取RGB颜色值
export const yf_tcs34725_begin_readrgb = function (_, generator) {
    var integration_time = this.getFieldValue('INTEGRATIONTIME');

    generator.definitions_['include_Wire'] = '#include <Wire.h>';
    generator.definitions_['include_tcs34725'] = '#include "Adafruit_TCS34725.h"';
    generator.definitions_['var_tcs34725'] = 'Adafruit_TCS34725 tcs = Adafruit_TCS34725('+integration_time+', TCS34725_GAIN_1X);';
    generator.setups_['setup_tcs34725_begin'] = 'tcs.begin();\n';
    var code = 'float r, g, b;\n' + 'tcs.getRGB(&r, &g, &b);\n';
    return code;
}

// 颜色传感器TCS34725 - 获取RGB颜色值
export const yf_tcs34725_get_rgb = function (_, generator) {
    var val_rgb = this.getFieldValue('VALUERGB');
    var code = '';
    if (val_rgb == 'r') {
        code += 'r';
    } else if (val_rgb == 'g') {
        code += 'g';
    } else if (val_rgb == 'b') {
        code += 'b';
    }
    return [code, generator.ORDER_ATOMIC];
}

// 颜色传感器VEML6040- 初始化
export const yf_veml6040_begin = function (_, generator) {
    generator.definitions_['include_Wire'] = '#include <Wire.h>';
    generator.definitions_['include_veml6040'] = '#include "veml6040.h"';
    generator.definitions_['var_veml6040'] = 'VEML6040 vemlSensor;';
    generator.setups_['setup_veml6040_begin'] = 'vemlSensor.begin();';
    generator.setups_['setup_veml6040_setConfig'] = 'vemlSensor.setConfiguration(VEML6040_IT_40MS + VEML6040_AF_AUTO + VEML6040_SD_ENABLE);';
    return "";
}

// 颜色传感器VEML6040 - 获取RGB颜色值
export const yf_veml6040_get_rgb = function (_, generator) {
    var val_rgb = this.getFieldValue('VALUERGB');
    var code = '';
    if (val_rgb == 'r') {
        code = 'vemlSensor.getRed()';
    } else if (val_rgb == 'g') {
        code = 'vemlSensor.getGreen()';
    } else if (val_rgb == 'b') {
        code = 'vemlSensor.getBlue()';
    }
    return [code, generator.ORDER_ATOMIC];
}

// 陀螺仪传感器MPU6050 - 获取数据
export const yf_mpu6050 = function (_, generator) {
    generator.definitions_['include_Wire'] = '#include <Wire.h>';
    generator.definitions_['includeMPU6050'] = '#include <MPU6050_tockn.h>';
    generator.definitions_['var_declare_MPU6050'] = 'MPU6050 mpu(Wire);';
    generator.setups_['setup_Wire_begin'] = 'Wire.begin();';
    generator.setups_['setup_mpu_begin'] = 'mpu.begin();';
    generator.setups_['setup_mpu_calcGyroOffsets'] = 'mpu.calcGyroOffsets(true);';
    var MPU6050_TYPE = this.getFieldValue('MPU6050_TYPE');
    var code = 'mpu.' + MPU6050_TYPE;
    return [code, generator.ORDER_ATOMIC];
}
// 陀螺仪传感器MPU6050 - 更新数据
export const yf_mpu6050_update = function () {
    var code = 'mpu.update();\n';
    return code;
}

// 心率血氧传感器MAX30102 - 初始化获取数据
export const yf_max30102_begin = function (_, generator) {
    generator.definitions_['include_Wire'] = '#include <Wire.h>';
    generator.definitions_['include_max30102'] = '#include "MAX30105.h"';
    generator.definitions_['include_heartRate'] = '#include "heartRate.h"';
    generator.definitions_['var_declare_max30102'] = 'MAX30105 particleSensor;';
    generator.definitions_['var_declare_RATE_SIZE'] = 'const byte RATE_SIZE = 4;';
    generator.definitions_['var_declare_rates[RATE_SIZE]'] = 'byte rates[RATE_SIZE];';
    generator.definitions_['var_declare_rateSpot'] = 'byte rateSpot = 0;';
    generator.definitions_['var_declare_lastBeat'] = 'long lastBeat = 0;';
    generator.definitions_['var_declare_beatsPerMinute'] = 'float beatsPerMinute;';
    generator.definitions_['var_declare_beatAvg'] = 'int beatAvg;';
    generator.setups_['setup_max30102_begin'] = 'particleSensor.begin();';
    generator.setups_['setup_max30102_setup'] = 'particleSensor.setup();';
    generator.setups_['setup_max30102_setPulseAmplitudeRed'] = 'particleSensor.setPulseAmplitudeRed(0x0A);';
    generator.setups_['setup_max30102_setPulseAmplitudeGreen'] = 'particleSensor.setPulseAmplitudeGreen(0);';
    var code = 'long irValue = particleSensor.getIR();\n' +
        'if (checkForBeat(irValue) == true) {\n' +
        '   long delta = millis() - lastBeat;\n' +
        '   lastBeat = millis();\n' +
        '   beatsPerMinute = 60 / (delta / 1000.0);\n' +
        '   if (beatsPerMinute < 255 && beatsPerMinute > 20) {\n' +
        '       rates[rateSpot++] = (byte)beatsPerMinute;\n' +
        '       rateSpot %= RATE_SIZE;\n' +
        '       beatAvg = 0;\n' +
        '       for (byte x = 0 ; x < RATE_SIZE ; x++)\n' +
        '           beatAvg += rates[x];\n' +
        '       beatAvg /= RATE_SIZE;\n' +
        '   }\n' +
        '}\n';
    return code;
}

// 心率血氧传感器MAX30102 - 获取每分钟心跳值Avg BPM
export const yf_max30102_get_bpm = function (_, generator) {
    var val_bpm_type = this.getFieldValue('MAX30102_BPM_TYPE');
    var code = '';
    if (val_bpm_type == 'BPM') {
        code += 'beatsPerMinute';
    } else if (val_bpm_type == 'AVGBPM') {
        code += 'beatAvg';
    } else if (val_bpm_type == 'IRVAL') {
        code += 'irValue';
    }
    return [code, generator.ORDER_ATOMIC];
}


// TOF激光测距传感器VL53L0X- 初始化
export const yf_tof_vl53l0x_begin = function (_, generator) {
    generator.definitions_['include_YFRobot_VL53L0X'] = '#include "YFRobot_VL53L0X.h"';
    generator.definitions_['var_declare_YFRobot_VL53L0X'] = 'YFRobot_VL53L0X vl53l0x;';
    generator.setups_['setup_vl53l0x_begin'] = 'vl53l0x.begin();';
    var code = '';
    return code;
}

// TOF激光测距传感器VL53L0X- 设置
export const yf_tof_vl53l0x_set = function () {
    var Atype = this.getFieldValue('ATYPE');
    var Btype = this.getFieldValue('BTYPE');
    var code = 'vl53l0x.setMode(vl53l0x.' + Atype + ', vl53l0x.' + Btype + ');';
    return code;
}

// TOF激光测距传感器VL53L0X- 测距
export const yf_tof_vl53l0x_getDistance = function (_, generator) {
    var code = 'vl53l0x.getDistance()';
    return [code, generator.ORDER_ATOMIC];
}

// 巡线I2C-5路传感器
export const yf_i2c_line_patrol_readSensor = function (_, generator) {
    // var linefollow_channel = generator.variableDB_.getName(this.getFieldValue('CHANNEL'), Blockly.Variables.NAME_TYPE);
    var linefollow_channel = this.getFieldValue('CHANNEL');

    // generator.definitions_['include_Wire'] = '#include <Wire.h>';
    generator.definitions_['define_yflinefollow_lib'] = '#include "YFLineFollow.h"';
    generator.definitions_['define_yflinefollow_class'] = 'YFLINEFOLLOW yfLS;';
    generator.setups_['setup_yflinefollow_begin'] = 'if (yfLS.begin() == false) {\n' +
        // '    Serial.println("Failed to communicate. Check wiring.");\n' +
        '    while (1) ; // If we fail to communicate, loop forever.\n' +
        '  }\n';

    generator.setups_['setup_yflinefollow_enable'] = 'yfLS.enableSensor(); // 使能传感器，默认使能';

    var code = 'yfLS.readSensor(' + linefollow_channel + ')';
    return [code, generator.ORDER_ATOMIC];
}

// 5路循迹传感器 QTR-5RC 初始化引脚配置，更新包括使能引脚
export const yf_qtr_5rc_init = function (_, generator) {
    // var qtrName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
    var dropdown_pin1 = generator.valueToCode(this, 'PINIR1', generator.ORDER_ATOMIC);
    var dropdown_pin2 = generator.valueToCode(this, 'PINIR2', generator.ORDER_ATOMIC);
    var dropdown_pin3 = generator.valueToCode(this, 'PINIR3', generator.ORDER_ATOMIC);
    var dropdown_pin4 = generator.valueToCode(this, 'PINIR4', generator.ORDER_ATOMIC);
    var dropdown_pin5 = generator.valueToCode(this, 'PINIR5', generator.ORDER_ATOMIC);
    var dropdown_pinen = generator.valueToCode(this, 'PINEN', generator.ORDER_ATOMIC);
    var NUM_SENSOR = 5;
    generator.definitions_['define_qtrlib'] = '#include "QTRSensors.h"';
    generator.definitions_['define_qtr_num_sensor'] = '#define NUM_SENSOR ' + NUM_SENSOR;
    // generator.definitions_['define_qtrclass'] = 'QTRSensors ' + qtrName +';';
    generator.definitions_['define_qtrclass'] = 'QTRSensors qtr;';
    generator.setups_['setup_output_setTypeRC'] = 'qtr.setTypeRC();';
    generator.setups_['setup_output_setSensorPins'] = 'qtr.setSensorPins((const uint8_t[]){' + dropdown_pin1 + ','
        + dropdown_pin2 + ',' + dropdown_pin3 + ',' + dropdown_pin4 + ',' + dropdown_pin5 + '}, NUM_SENSOR);';
    generator.setups_['setup_output_setEmitterPin'] = 'qtr.setEmitterPin(' + dropdown_pinen + ');';
    return '';
}

// 5路循迹传感器 QTR-5RC 校准
export const yf_qtr_5rc_calibrate = function () {
    var code = 'qtr.calibrate();\n';
    return code;
}

// 5路循迹传感器 QTR-5RC 读取传感器
export const yf_qtr_5rc_readLineBlack = function (_, generator) {
    var qtrsensorValues = generator.variableDB_.getName(this.getFieldValue('VARVALUE'), Blockly.Variables.NAME_TYPE);
    // var qtrName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
    generator.definitions_['define_qtr' + qtrsensorValues] = 'uint16_t ' + qtrsensorValues + '[NUM_SENSOR];';
    // var code =qtrName+'.readLineBlack('+qtrsensorValues+');';
    var code = 'qtr.readLineBlack(' + qtrsensorValues + ')';
    return [code, generator.ORDER_ATOMIC];
}

// 获取读取到的传感器值
export const yf_qtr_5rc_getValue = function (_, generator) {
    var qtrsensorValues = generator.variableDB_.getName(this.getFieldValue('VARVALUE'), Blockly.Variables.NAME_TYPE);
    var linefollow_qtr_channel = this.getFieldValue('CHANNEL');
    // var code = 'yfLS.readSensor('+linefollow_channel+')';
    var code = qtrsensorValues + '[' + linefollow_qtr_channel + ']';
    return [code, generator.ORDER_ATOMIC];
}

// 5路循迹传感器 QTR-5RC 读取传感器(无需校准，读原始传感器值)
export const yf_qtr_5rc_readWithoutCalibrate = function (_, generator) {
    var qtrsensorValues = generator.variableDB_.getName(this.getFieldValue('VARVALUE'), Blockly.Variables.NAME_TYPE);
    generator.definitions_['define_qtr' + qtrsensorValues] = 'uint16_t ' + qtrsensorValues + '[NUM_SENSOR];';
    var code = 'qtr.read(' + qtrsensorValues + ');\n';
    return code;
}


/************************** GPS 定位模块 ***************************/
export const yf_gps_init = function (_, generator) {
    var rx = generator.valueToCode(this, 'RX', generator.ORDER_ATOMIC);
    var tx = generator.valueToCode(this, 'TX', generator.ORDER_ATOMIC);
    var bt = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC)
    generator.definitions_['include_TinyGPS++'] = '#include <TinyGPS++.h>';
    generator.definitions_['var_declare_TinyGPSPlus_gps'] = 'TinyGPSPlus gps;';
    var board_type = Mixly.Boards.getType();  // 获取板型

    if(board_type == "arduino_esp32" || board_type == "arduino_esp32s3" || board_type == "arduino_esp32c3"){
        generator.definitions_['include_HardwareSerial'] = '#include <HardwareSerial.h>';
        generator.definitions_['var_declare_HardwareSerial_gps_ss_Serial1'] = '#define gps_ss Serial1';
        generator.setups_['var_declare_HardwareSerial_gps_ss' + rx + tx] = 'gps_ss.begin(' + bt + ',SERIAL_8N1,'+ rx + ', ' + tx + ');';
    } else if(board_type == "arduino_avr") {
        generator.definitions_['include_SoftwareSerial'] = '#include <SoftwareSerial.h>';
        generator.definitions_['var_declare_SoftwareSerial_gps_ss'] = 'SoftwareSerial gps_ss(' + rx + ', ' + tx + ');';
        generator.setups_['setup_gps_ss_begin'] = 'gps_ss.begin(' + bt + ');';
    }
    return '';
};

export const yf_gps_data_available = function (_, generator) {
    var code = 'gps_ss.available()';
    return [code, generator.ORDER_ATOMIC];
};

export const yf_gps_data_encode = function (_, generator) {
    var code = 'gps.encode(gps_ss.read())';
    return [code, generator.ORDER_ATOMIC];
};

export const yf_gps_xxx_isValid = function (_, generator) {
    var WHAT = this.getFieldValue('WHAT');
    var code = 'gps.' + WHAT + '.isValid()';
    return [code, generator.ORDER_ATOMIC];
};

export const yf_gps_getData_xxx = function (_, generator) {
    var WHAT = this.getFieldValue('WHAT');
    var code = 'gps.' + WHAT + '()';
    return [code, generator.ORDER_ATOMIC];
};
export const yf_gps_GSV_init = function (_, generator) {
    generator.definitions_['var_declare_gps_gsv_MAX_SATELLITES'] = 'static const int MAX_SATELLITES = 40;';
    generator.definitions_['var_declare_gps_gsv_totalGPGSVMessages'] = 'TinyGPSCustom totalGPGSVMessages(gps, "GPGSV", 1);';
    generator.definitions_['var_declare_gps_gsv_messageNumber'] = 'TinyGPSCustom messageNumber(gps, "GPGSV", 2);';
    generator.definitions_['var_declare_gps_gsv_satsInView'] = 'TinyGPSCustom satsInView(gps, "GPGSV", 3);';
    generator.definitions_['var_declare_gps_gsv_satNumber'] = 'TinyGPSCustom satNumber[4];';
    generator.definitions_['var_declare_gps_gsv_elevation'] = 'TinyGPSCustom elevation[4];';
    generator.definitions_['var_declare_gps_gsv_azimuth'] = 'TinyGPSCustom azimuth[4];';
    generator.definitions_['var_declare_gps_gsv_snr'] = 'TinyGPSCustom snr[4];';
    generator.definitions_['var_declare_gps_gsv_sats'] = 'struct { \n  bool active; \n  int elevation;\n  int azimuth;\n  int snr;\n} sats[MAX_SATELLITES];';
    generator.setups_['setup_gps_gsv_TinyGPSCustom'] = '// Initialize all the uninitialized TinyGPSCustom objects\n'+
    '  for (int i = 0; i < 4; ++i) { \n'+
    '    satNumber[i].begin(gps, "GPGSV", 4 + 4 * i);  // offsets 4, 8, 12, 16\n'+
    '    elevation[i].begin(gps, "GPGSV", 5 + 4 * i);  // offsets 5, 9, 13, 17\n'+
    '    azimuth[i].begin(gps, "GPGSV", 6 + 4 * i);    // offsets 6, 10, 14, 18\n'+
    '    snr[i].begin(gps, "GPGSV", 7 + 4 * i);        // offsets 7, 11, 15, 19\n'+
    '  }';
    return '';
};
export const yf_gps_gsv_MS_isUpdated = function (_, generator) {
    var GROUP = this.getFieldValue('GROUP');
    var code = 'totalGPGSVMessages.isUpdated() && atoi(messageNumber.value())==' + GROUP;
    return [code, generator.ORDER_ATOMIC];
};
export const yf_gps_GSV_getData = function (_, generator) {
    var WHAT = this.getFieldValue('WHAT');
    var NUM = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC) || '0';
    var code = 'atoi(' + WHAT + '['+ NUM + '-1].value())';
    return [code, generator.ORDER_ATOMIC];
};
// 外部列表
export const yf_gps_GSV_list1 = function (_, generator) {
    var code = this.getFieldValue('VAR');
    return [code, generator.ORDER_ATOMIC];
};


/********************************************
MUSIC - 音乐
*********************************************/
//Music-播放音乐函数-设置基准音调频率 默认C
export const yf_tone_list = function (_, generator) {
    var varTone = this.getFieldValue('TONE');
    var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
    var text;
    if (varTone == "C") text = '261.6 , 293.7 , 329.6 , 349.2 , 392.0 , 440.0 , 493.9';             // C
    else if (varTone == "#C") text = '277.2 , 311.1 , 349.2 , 367.0 , 415.3 , 466.2 , 523.3';      // C#
    else if (varTone == "D") text = '293.7 , 329.6 , 367.0 , 392.0 , 440.0 , 493.9 , 554.4';      // D
    else if (varTone == "#D") text = '311.1 , 349.2 , 392.0 , 415.3 , 466.2 , 523.3 , 587.3';      // D#
    else if (varTone == "E") text = '329.6 , 367.0 , 415.3 , 440.0 , 493.9 , 554.4 , 622.3';      // E
    else if (varTone == "F") text = '349.2 , 392.0 , 440.0 , 466.2 , 523.3 , 587.3 , 659.3';      // F
    else if (varTone == "#F") text = '367.0 , 415.3 , 466.2 , 493.9 , 554.4 , 622.3 , 698.5';      // F#
    else if (varTone == "G") text = '392.0 , 440.0 , 493.9 , 523.3 , 587.3 , 659.3 , 740.0';      // G
    else if (varTone == "#G") text = '415.3 , 466.2 , 523.3 , 554.4 , 622.3 , 698.5 , 784.0';      // G#
    else if (varTone == "A") text = '440.0 , 493.9 , 554.4 , 587.3 , 659.3 , 740.0 , 830.6';      // A
    else if (varTone == "#A") text = '466.2 , 523.3 , 587.3 , 622.3 , 698.5 , 784.0 , 880.0';      // A#
    else if (varTone == "B") text = '493.9 , 554.4 , 622.3 , 659.3 , 740.0 , 830.6 , 932.3';      // B

    generator.definitions_['var_' + varName] = 'float ' + varName + '[7]' + '=' + '{' + text + '};\n';
    return '';
}

//Music-播放音乐函数-设置音符
export const yf_set_musiclist = function (_, generator) {
    var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
    // var size = window.parseFloat(this.getFieldValue('SIZE'));
    var text = this.getFieldValue('TEXT');
    generator.definitions_['var_' + varName] = 'long ' + varName + '[ ]' + '=' + '{' + text + '};\n';
    return '';
}

//Music-播放音乐函数-设置音高
export const yf_set_highlist = yf_set_musiclist;

//Music-播放音乐函数-设置时值
export const yf_set_rhythmlist = function (_, generator) {
    var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
    // var size = window.parseFloat(this.getFieldValue('SIZE'));
    var text = this.getFieldValue('TEXT');
    generator.definitions_['var_' + varName] = 'float ' + varName + '[ ]' + '=' + '{' + text + '};\n';
    return '';
}

//Music-播放音乐函数-设置每拍时长
export const yf_set_tone_duration = function (_, generator) {
    var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
    var num = this.getFieldValue('NUMBER');
    generator.definitions_['var_' + varName] = 'float ' + varName + '=' + num + ';\n';
    return '';
}


/********************************************
DISPLAY - 显示
*********************************************/
// Blockly.rgb_display_ledcount = 'rgb_display';
//RGB
export const yf_display_rgb_init = function (_, generator) {
    var dropdown_rgbpin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var value_ledcount = generator.valueToCode(this, 'LEDCOUNT', generator.ORDER_ATOMIC);
    generator.definitions_['include_Adafruit_NeoPixel'] = '#include "Adafruit_NeoPixel.h"';
    generator.definitions_['var_declare_rgb_display'] = 'Adafruit_NeoPixel rgb_display' + dropdown_rgbpin + '(' + value_ledcount + ',' + dropdown_rgbpin + ', NEO_GRB + NEO_KHZ800);';
    generator.setups_['setup_rgb_displaybegin_' + dropdown_rgbpin] = 'rgb_display' + dropdown_rgbpin + '.begin();';
    generator.setups_['setup_rgb_display_initshow' + dropdown_rgbpin] = 'rgb_display' + dropdown_rgbpin + '.clear();  // Initialize all pixels to off';
    return '';
}

export const yf_display_rgb = function (_, generator) {
    var dropdown_rgbpin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var value_led = generator.valueToCode(this, '_LED_', generator.ORDER_ATOMIC);
    var color = generator.valueToCode(this, 'COLOR', generator.ORDER_ATOMIC);
    color = color.replace(/#/g, "0x");
    var code = 'rgb_display' + dropdown_rgbpin + '.setPixelColor(' + value_led + '-1, ' + color + ');\n';
    return code;
}

export const yf_display_rgb_color_seclet = function (_, generator) {
    var colour = this.getFieldValue('COLOR');
    colour = '0x' + colour.substring(1, colour.length);
    return [colour, generator.ORDER_NONE];
}

export const yf_display_rgb_color_rgb = function (_, generator) {
    var R = generator.valueToCode(this, 'R', generator.ORDER_ATOMIC);
    var G = generator.valueToCode(this, 'G', generator.ORDER_ATOMIC);
    var B = generator.valueToCode(this, 'B', generator.ORDER_ATOMIC);
    var colour = "((" + R + " & 0xffffff) << 16) | ((" + G + " & 0xffffff) << 8) | " + B;
    return [colour, generator.ORDER_NONE];
}

export const yf_display_rgb_setbrightness = function (_, generator) {
    var dropdown_rgbpin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var rgb_brightness = generator.valueToCode(this, 'BRIGHTNESS', generator.ORDER_ATOMIC);
    var code = 'rgb_display' + dropdown_rgbpin + '.setBrightness(' + rgb_brightness + ');\n';
    return code;
}

export const yf_display_rgb_show = function (_, generator) {
    // var board_type = JSFuncs.getPlatform();
    var dropdown_rgbpin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var code = 'rgb_display' + dropdown_rgbpin + '.show();\n';
    // if (board_type.match(RegExp(/ESP32/))) {
    //     code+='rgb_display' + dropdown_rgbpin + '.show();\n';
    // }
    return code;
}

// 0.96OLED显示-初始化(iic)
export const yf_oled_init = function (_, generator) {
    var OLED_TYPE = this.getFieldValue('OLED_TYPE');
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var ROTATION = this.getFieldValue('ROTATION');
    var SDA = this.getFieldValue('SDA');
    var SCL = this.getFieldValue('SCL');
    var ADDRESS = generator.valueToCode(this, 'ADDRESS', generator.ORDER_ATOMIC) || '0x3D';
    var board_type = JSFuncs.getPlatform();
    // var mixlyverson = Mixly.Config.SOFTWARE.version; // 获取软件版本号
    // var mixlyverson = MixlyConfig.softwareConfig.version;// 获取软件版本号2
    // if(mixlyverson == "Mixly 2.0"){
    //     var board_type = JSFuncs.getPlatform(); // Mixly V2.0
    // }else {
    //     var board_type = JSFuncs.getPlatform(); // Mixly V1.0
    // }
    // var board_type ="ESP8266";
    // generator.definitions_['include_Wire'] = '#include <Wire.h>';
    generator.definitions_['include_U8g2lib'] = '#include <U8g2lib.h>';
    // if(SDA == window.profile.default.SDA[0][1] && SCL == window.profile.default.SCL[0][1])
    //     generator.definitions_['var_declare_U8G2'+NAME] ='U8G2_'+OLED_TYPE+'_F_SW_I2C '+NAME+'('+ROTATION+',  '+SCL+', '+SDA+', U8X8_PIN_NONE);';
    if (board_type.match(RegExp(/AVR/))) {
        if (SDA == window.profile.default.SDA[0][1] && SCL == window.profile.default.SCL[0][1])
            generator.definitions_['var_declare_U8G2' + NAME] = 'U8G2_' + OLED_TYPE + '_1_HW_I2C ' + NAME + '(' + ROTATION + ', U8X8_PIN_NONE);';
        else
            generator.definitions_['var_declare_U8G2' + NAME] = 'U8G2_' + OLED_TYPE + '_1_SW_I2C ' + NAME + '(' + ROTATION + ',  ' + SCL + ', ' + SDA + ', U8X8_PIN_NONE);';
    }
    else {
        if (SDA == window.profile.default.SDA[0][1] && SCL == window.profile.default.SCL[0][1])
            generator.definitions_['var_declare_U8G2' + NAME] = 'U8G2_' + OLED_TYPE + '_F_HW_I2C ' + NAME + '(' + ROTATION + ', U8X8_PIN_NONE);';
        else
            generator.definitions_['var_declare_U8G2' + NAME] = 'U8G2_' + OLED_TYPE + '_F_SW_I2C ' + NAME + '(' + ROTATION + ',  ' + SCL + ', ' + SDA + ', U8X8_PIN_NONE);';
    }
    generator.setups_["setup_u8g2" + NAME] = NAME + '.setI2CAddress(' + ADDRESS + '*2);\n'
        + '  ' + NAME + '.begin();';
    var code = '';
    return code;
}

export const yf_oled_page = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var branch = generator.statementToCode(this, 'DO');
    //branch = branch.replace(/(^\s*)|(\s*$)/g, "");
    var code = '';
    if (branch) {
        code = NAME + ".firstPage();"
            + "\ndo"
            + "\n{"
            + "\n" + branch
            + "}while(" + NAME + ".nextPage());\n";
    }
    return code;
}

export const yf_oled_clear = function () {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var code = NAME + ".clearDisplay();\n";
    return code;
}

export const yf_oled_face = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var POS_x = generator.valueToCode(this, 'POS_X', generator.ORDER_ATOMIC) || '0';
    var POS_y = generator.valueToCode(this, 'POS_Y', generator.ORDER_ATOMIC) || '0';
    var FACE_IMAGE = this.getFieldValue('FACE_IMAGE');
    var pos = FACE_IMAGE.indexOf(',');
    var varName = "FACE_" + FACE_IMAGE.substring(0, pos);
    FACE_IMAGE = FACE_IMAGE.substring(pos + 1, FACE_IMAGE.length);
    // YANG use PROGMEM to save the RAM space
    //generator.definitions_['var_declare' + varName] = 'static unsigned char ' + varName + '[]={' + FACE_IMAGE + ' };\n';
    //var code="u8g2.drawXBM("+POS_x+","+POS_y+",89,64,"+varName+");\n";
    generator.definitions_['var_declare' + varName] = 'const static unsigned char ' + varName + '[] PROGMEM ={' + FACE_IMAGE + ' };\n';
    var code = NAME + ".drawXBMP(" + POS_x + "," + POS_y + ",89,64," + varName + ");\n";
    return code;
}

export const yf_oled_icons = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var POS_x = generator.valueToCode(this, 'POS_X', generator.ORDER_ATOMIC) || '0';
    var POS_y = generator.valueToCode(this, 'POS_Y', generator.ORDER_ATOMIC) || '0';
    var ICON_SIZE = this.getFieldValue('ICON_SIZE');
    var ICON_IMAGE = this.getFieldValue('ICON_IMAGE');
    var code = NAME + ".setFont(u8g2_font_open_iconic_all_" + ICON_SIZE + "x_t);\n"
        + NAME + ".drawGlyph(" + POS_x + "," + POS_y + "+" + ICON_SIZE + "*8," + ICON_IMAGE + ");\n";
    return code;
}

export const yf_oled_drawPixel = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var pos_x = generator.valueToCode(this, 'POS_X', generator.ORDER_ATOMIC) || '0';
    var pos_y = generator.valueToCode(this, 'POS_Y', generator.ORDER_ATOMIC) || '0';
    var code = "";
    code = code + NAME + '.drawPixel(' + pos_x + ',';
    code += pos_y + ');\n';
    return code;
}

export const yf_oled_define_bitmap_data = function (_, generator) {
    var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
    var text = this.getFieldValue('TEXT');
    //YANG use PROGMEM to save the RAM space
    //generator.definitions_['var_declare' + varName] = 'static unsigned char ' + varName + '[]={' + text + ' }\n';
    generator.definitions_['var_declare' + varName] = 'const static unsigned char ' + varName + '[] PROGMEM ={' + text + ' };\n';
    return '';
}

export const yf_oled_showBitmap = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var start_x = generator.valueToCode(this, 'START_X', generator.ORDER_ATOMIC) || '0';
    var start_y = generator.valueToCode(this, 'START_Y', generator.ORDER_ATOMIC) || '0';
    var width = generator.valueToCode(this, 'WIDTH', generator.ORDER_ATOMIC) || '0';
    var height = generator.valueToCode(this, 'HEIGHT', generator.ORDER_ATOMIC) || '0';
    var data_name = generator.valueToCode(this, 'bitmap_name', generator.ORDER_ATOMIC);
    data_name = data_name.replace(/"/g, "");
    var code = "";
    //YANG use PROGMEM to save the RAM space
    //code = 'u8g2.drawXBM(' + start_x + ', ';
    code = NAME + '.drawXBMP(' + start_x + ', ';
    code += start_y + ', ';
    code += width + ', ';
    code += height + ', ' + data_name + ');\n';
    return code;
}

export const yf_oled_drawLine = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var start_x = generator.valueToCode(this, 'START_X', generator.ORDER_ATOMIC) || '0';
    var start_y = generator.valueToCode(this, 'START_Y', generator.ORDER_ATOMIC) || '0';
    var end_x = generator.valueToCode(this, 'END_X', generator.ORDER_ATOMIC) || '0';
    var end_y = generator.valueToCode(this, 'END_Y', generator.ORDER_ATOMIC) || '0';
    var code = "";
    code = NAME + '.drawLine(' + start_x + ',';
    code += start_y + ',';
    code += end_x + ',';
    code += end_y + ');\n';
    return code;
}

export const yf_oled_draw_Str_Line = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var start_x = generator.valueToCode(this, 'START_X', generator.ORDER_ATOMIC) || '0';
    var start_y = generator.valueToCode(this, 'START_Y', generator.ORDER_ATOMIC) || '0';
    var length = generator.valueToCode(this, 'LENGTH', generator.ORDER_ATOMIC) || '0';
    var TYPE = this.getFieldValue('TYPE');
    var code = "";
    code = NAME + ".draw" + TYPE + "Line(" + start_x + ',';
    code += start_y + ',';
    code += length + ');\n';
    return code;
}

export const yf_oled_drawTriangle = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var D0_x = generator.valueToCode(this, 'D0_X', generator.ORDER_ATOMIC) || '0';
    var D0_y = generator.valueToCode(this, 'D0_Y', generator.ORDER_ATOMIC) || '0';
    var D1_x = generator.valueToCode(this, 'D1_X', generator.ORDER_ATOMIC) || '0';
    var D1_y = generator.valueToCode(this, 'D1_Y', generator.ORDER_ATOMIC) || '0';
    var D2_x = generator.valueToCode(this, 'D2_X', generator.ORDER_ATOMIC) || '0';
    var D2_y = generator.valueToCode(this, 'D2_Y', generator.ORDER_ATOMIC) || '0';
    var code = "";
    code = NAME + '.drawTriangle(' + D0_x + ',';
    code += D0_y + ',';
    code += D1_x + ',';
    code += D1_y + ',';
    code += D2_x + ',';
    code += D2_y + ');\n';
    return code;
}

export const yf_oled_drawFrame = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var D0_x = generator.valueToCode(this, 'D0_X', generator.ORDER_ATOMIC) || '0';
    var D0_y = generator.valueToCode(this, 'D0_Y', generator.ORDER_ATOMIC) || '0';
    var Width = generator.valueToCode(this, 'WIDTH', generator.ORDER_ATOMIC) || '0';
    var Height = generator.valueToCode(this, 'HEIGHT', generator.ORDER_ATOMIC) || '0';
    var type = this.getFieldValue('TYPE');
    var code = "";
    code = NAME + '.' + type + '(' + D0_x + ',';
    code += D0_y + ',';
    code += Width + ',';
    code += Height + ');\n';
    return code;
}

export const yf_oled_drawRFrame = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var D0_x = generator.valueToCode(this, 'D0_X', generator.ORDER_ATOMIC) || '0';
    var D0_y = generator.valueToCode(this, 'D0_Y', generator.ORDER_ATOMIC) || '0';
    var Width = generator.valueToCode(this, 'WIDTH', generator.ORDER_ATOMIC) || '0';
    var Height = generator.valueToCode(this, 'HEIGHT', generator.ORDER_ATOMIC) || '0';
    var Rauius = generator.valueToCode(this, 'RADIUS', generator.ORDER_ATOMIC) || '0';
    var type = this.getFieldValue('TYPE');
    var code = "";
    code = NAME + '.' + type + '(' + D0_x + ',';
    code += D0_y + ',';
    code += Width + ',';
    code += Height + ',';
    code += Rauius + ');\n';
    return code;
}

export const yf_oled_drawCircle = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var D0_x = generator.valueToCode(this, 'D0_X', generator.ORDER_ATOMIC) || '0';
    var D0_y = generator.valueToCode(this, 'D0_Y', generator.ORDER_ATOMIC) || '0';
    var Rauius = generator.valueToCode(this, 'RADIUS', generator.ORDER_ATOMIC) || '0';
    var type = this.getFieldValue('TYPE');
    var opt = this.getFieldValue('OPT');
    var code = "";
    code = NAME + '.' + type + '(' + D0_x + ',';
    code += D0_y + ',';
    code += Rauius + "," + opt + "); \n";
    return code;
}

export const yf_oled_drawEllipse = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var D0_x = generator.valueToCode(this, 'D0_X', generator.ORDER_ATOMIC) || '0';
    var D0_y = generator.valueToCode(this, 'D0_Y', generator.ORDER_ATOMIC) || '0';
    var Rauius_X = generator.valueToCode(this, 'RADIUS_X', generator.ORDER_ATOMIC) || '0';
    var Rauius_Y = generator.valueToCode(this, 'RADIUS_Y', generator.ORDER_ATOMIC) || '0';
    var type = this.getFieldValue('TYPE');
    var opt = this.getFieldValue('OPT');
    var code = "";
    code = NAME + '.' + type + '(' + D0_x + ',';
    code += D0_y + ',';
    code += Rauius_X + ",";
    code += Rauius_Y + "," + opt + "); \n";
    return code;
}

export const yf_oled_print = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var POS_x = generator.valueToCode(this, 'POS_X', generator.ORDER_ATOMIC) || '0';
    var POS_y = generator.valueToCode(this, 'POS_Y', generator.ORDER_ATOMIC) || '0';
    var TEXT = generator.valueToCode(this, 'TEXT', generator.ORDER_ATOMIC) || '0';
    generator.setups_["setup_enableUTF8Print" + NAME] = NAME + '.enableUTF8Print();\n';
    var code = "";
    code = NAME + '.setCursor(' + POS_x + ',';
    code += POS_y + "); \n";
    code += NAME + ".print(" + TEXT + "); \n";
    return code;
}

export const yf_oled_set_EN_Font = function () {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var FONT_NAME = this.getFieldValue('FONT_NAME');
    var FONT_SIZE = this.getFieldValue('FONT_SIZE');
    var FONT_STYLE = this.getFieldValue('FONT_STYLE');
    var code = NAME + ".setFont(u8g2_font_" + FONT_NAME + FONT_STYLE + FONT_SIZE + "_tf);\n" + NAME + ".setFontPosTop();\n";
    return code;
}

export const yf_oled_set_CN_Font = function () {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var FONT_NAME = this.getFieldValue('FONT_NAME');
    var FONT_SIZE = this.getFieldValue('FONT_SIZE');
    var code = NAME + ".setFont(u8g2_font_" + FONT_SIZE + FONT_NAME + ");\n" + NAME + ".setFontPosTop();\n";
    return code;
}

// 0.96OLED显示-背光亮度
export const yf_u8g2_setContrast = function (_, generator) {
    var NAME = this.getFieldValue('NAME') || 'u8g2';
    var Contrast = generator.valueToCode(this, 'Contrast', generator.ORDER_ATOMIC);
    var code = NAME + '.setContrast(' + Contrast + ');\n';
    return code;
}

// Matrix57 点阵显示 - 初始化
export const yf_dotMatrix57_init = function (_, generator) {
    var CLK = generator.valueToCode(this, 'PINCLK', generator.ORDER_ATOMIC || '9');
    var DIO = generator.valueToCode(this, 'PINDAT', generator.ORDER_ATOMIC || '10');
    generator.definitions_['include_Matrix57'] = '#include "Matrix57.h"';
    generator.definitions_['var_display_matrix57'] = 'Matrix57 matrix57(' + CLK + ',' + DIO + ');';
    generator.setups_['setup_matrix57_init'] = 'matrix57.init();\n';
    return '';
}

// Matrix57 点阵显示 - 清屏
export const yf_dotMatrix57_clear = function () {
    var code = "matrix57.clearDisplay();\n";
    return code;
}

// Matrix57 点阵显示 - 设置亮度
export const yf_dotMatrix57_Brightness = function (_, generator) {
    var brightness = generator.valueToCode(this, 'brightness', generator.ORDER_ASSIGNMENT) || '2';
    var code = 'matrix57.set(' + brightness + ');\n';
    return code;
}

// Matrix57 点阵显示 - 数组
export const yf_dotMatrix57_CharArray = function (_, generator) {
    var varName = this.getFieldValue('VAR');
    var a = new Array();
    for (let i = 1; i < 6; i++) {
        a[i] = new Array();
        for (let j = 1; j < 8; j++) {
            a[i][j] = (this.getFieldValue('a' + i + j) == "TRUE") ? 1 : 0;
        }
    }
    var code = '{';
    for (let i = 1; i < 6; i++) {
        var tmp = ""
        for (let j = 1; j < 8; j++) {
            tmp += a[i][j];
        }
        tmp = (parseInt(tmp, 2)).toString(16)
        if (tmp.length == 1) tmp = "0" + tmp;
        code += '0x' + tmp + ((i != 8) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_[varName] = "int8_t " + varName + "[]=" + code;
    return [varName, generator.ORDER_ATOMIC];
}

// Matrix57 点阵显示 - 全屏
export const yf_dotMatrix57_displayC = function (_, generator) {
    var lc_chars = generator.valueToCode(this, 'Chars', generator.ORDER_ATOMIC);
    var code = 'matrix57.display(' + lc_chars + ');\n';
    return code;
}

// Matrix57 点阵显示 - 点
export const yf_dotMatrix57_displayDot = function (_, generator) {
    var row = generator.valueToCode(this, 'row', generator.ORDER_ATOMIC);
    var column = generator.valueToCode(this, 'column', generator.ORDER_ATOMIC);
    // var data = 1 << (7-column);
    var code = 'matrix57.display((' + row + '-1), + 1<<(7-' + column + '));\n';
    return code;
}

// LCD 1602
export const yf_lcd_init = function (_, generator) {
    var varName = this.getFieldValue('VAR');
    var device = generator.valueToCode(this, 'device', generator.ORDER_ATOMIC) || '0x27';
    generator.definitions_['include_Wire'] = '#include <Wire.h>';
    generator.definitions_['define_i2c_lcd'] = '#include <LiquidCrystal_I2C.h>';
    generator.definitions_['var_LiquidCrystal_I2C_' + varName] = 'LiquidCrystal_I2C ' + varName + '(' + device + ', 16, 2);';
    return '';
}

export const yf_lcd_print = function (_, generator) {
    var varName = this.getFieldValue('VAR');
    var str1 = generator.valueToCode(this, 'TEXT', generator.ORDER_ATOMIC) || '""';
    var str2 = generator.valueToCode(this, 'TEXT2', generator.ORDER_ATOMIC) || '""';
    if (generator.definitions_['var_LiquidCrystal_SoftI2C_' + varName] || generator.definitions_['var_LiquidCrystal_I2C_' + varName]) {
        generator.setups_['setup_lcd_init_' + varName] = varName + '.init();';
        // generator.setups_['setup_lcd_backlight_' + varName] = varName + '.backlight();';
    }
    var code = varName + '.setCursor(0, 0);\n'
    code += varName + '.print(' + str1 + ');\n';
    code += varName + '.setCursor(0, 1);\n';
    code += varName + '.print(' + str2 + ');\n';
    return code;
}

export const yf_lcd_print2 = function (_, generator) {
    var varName = this.getFieldValue('VAR');
    var str = generator.valueToCode(this, 'TEXT', generator.ORDER_ATOMIC) || 'String("")';
    var row = generator.valueToCode(this, 'row', generator.ORDER_ATOMIC) || '1';
    var column = generator.valueToCode(this, 'column', generator.ORDER_ATOMIC) || '1';
    if (generator.definitions_['var_LiquidCrystal_SoftI2C_' + varName] || generator.definitions_['var_LiquidCrystal_I2C_' + varName]) {
        generator.setups_['setup_lcd_init_' + varName] = varName + '.init();';
        // generator.setups_['setup_lcd_backlight_' + varName] = varName + '.backlight();';
    }
    var code = varName + '.setCursor(' + column + '-1,' + row + '-1);\n'
    code += varName + '.print(' + str + ');\n';
    return code;
}

export const yf_lcd_power = function (_, generator) {
    var varName = this.getFieldValue('VAR');
    var dropdown_stat = this.getFieldValue('STAT');
    if (generator.definitions_['var_LiquidCrystal_SoftI2C_' + varName] || generator.definitions_['var_LiquidCrystal_I2C_' + varName]) {
        generator.setups_['setup_lcd_init_' + varName] = varName + '.init();';
        // generator.setups_['setup_lcd_backlight_' + varName] = varName + '.backlight();';
    }
    var code = varName + '.' + dropdown_stat + '();\n'
    return code;
}

// export const yf_lcd_customChar = function() {
//   var varName = this.getFieldValue('VAR');
//   var customChar_num = generator.valueToCode(this, 'number', generator.ORDER_ATOMIC) || '0';
//   if (generator.definitions_['var_LiquidCrystal_SoftI2C_' + varName] || generator.definitions_['var_LiquidCrystal_I2C_' + varName]) {
//       generator.setups_['setup_lcd_init_' + varName] = varName + '.init();';
//       generator.setups_['setup_lcd_backlight_' + varName] = varName + '.backlight();';
//   }
//   var lc_chars = generator.valueToCode(this, 'Chars', generator.ORDER_ATOMIC);
//   generator.setups_['setup_create_char_' + varName + customChar_num] = varName + '.createChar('+ customChar_num+','+lc_chars+');';
//   return '';
// }

export const yf_lcd_write_customChar = function (_, generator) {
    var varName = this.getFieldValue('VAR');
    var row = generator.valueToCode(this, 'row', generator.ORDER_ATOMIC) || '1';
    var column = generator.valueToCode(this, 'column', generator.ORDER_ATOMIC) || '1';
    var customChar_num = generator.valueToCode(this, 'number', generator.ORDER_ATOMIC) || '0';
    if (generator.definitions_['var_LiquidCrystal_SoftI2C_' + varName] || generator.definitions_['var_LiquidCrystal_I2C_' + varName]) {
        generator.setups_['setup_lcd_init_' + varName] = varName + '.init();';
        // generator.setups_['setup_lcd_backlight_' + varName] = varName + '.backlight();';
    }
    var lc_chars = generator.valueToCode(this, 'Chars', generator.ORDER_ATOMIC);
    generator.setups_['setup_create_char_' + varName + customChar_num] = varName + '.createChar(' + customChar_num + ',' + lc_chars + ');';
    var code = varName + '.setCursor(' + column + '-1,' + row + '-1);\n'
    code += varName + '.write(byte(' + customChar_num + '));\n';
    return code;
}

export const yf_lcd_write_preset_customChar = function (_, generator) {
    var varName = this.getFieldValue('VAR');
    var row = generator.valueToCode(this, 'row', generator.ORDER_ATOMIC) || '1';
    var column = generator.valueToCode(this, 'column', generator.ORDER_ATOMIC) || '1';
    var customChar_num = generator.valueToCode(this, 'number', generator.ORDER_ATOMIC) || '0';
    if (generator.definitions_['var_LiquidCrystal_SoftI2C_' + varName] || generator.definitions_['var_LiquidCrystal_I2C_' + varName]) {
        generator.setups_['setup_lcd_init_' + varName] = varName + '.init();';
        // generator.setups_['setup_lcd_backlight_' + varName] = varName + '.backlight();';
    }
    var lc_chars = generator.valueToCode(this, 'PresetChars', generator.ORDER_ATOMIC);
    generator.setups_['setup_create_char_' + varName + customChar_num] = varName + '.createChar(' + customChar_num + ',' + lc_chars + ');';
    var code = varName + '.setCursor(' + column + '-1,' + row + '-1);\n'
    code += varName + '.write(byte(' + customChar_num + '));\n';
    return code;
}

//显示 - 自定义字符数组
export const CharArray = function (_, generator) {
    var varName = this.getFieldValue('VAR');
    var a = new Array();
    for (let i = 1; i < 9; i++) {
        a[i] = new Array();
        for (let j = 1; j < 6; j++) {
            a[i][j] = (this.getFieldValue('a' + i + j) == "TRUE") ? 1 : 0;
        }
    }
    var code = '{';
    for (let i = 1; i < 9; i++) {
        var tmp = ""
        for (let j = 1; j < 6; j++) {
            tmp += a[i][j];
        }
        tmp = (parseInt(tmp, 2)).toString(16)
        if (tmp.length == 1) tmp = "0" + tmp;
        code += '0x' + tmp + ((i != 8) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_[varName] = "byte " + varName + "[]=" + code;
    return [varName, generator.ORDER_ATOMIC];
}

// 预设字符-数据
var MIXLY_YF_PCUSTOMCHAR = [
    "0x00,0x0a,0x1f,0x1f,0x0e,0x04,0x00,0x00", "0x04,0x0e,0x0e,0x0e,0x1f,0x00,0x04,0x00",  //♥ bell
    "0x18,0x18,0x06,0x09,0x08,0x08,0x09,0x06", "0x00,0x04,0x0e,0x15,0x04,0x04,0x00,0x00",  //℃ ↑
    "0x00,0x04,0x04,0x15,0x0e,0x04,0x00,0x00", "0x00,0x04,0x08,0x1f,0x08,0x04,0x00,0x00",  //↓ ←
    "0x00,0x04,0x02,0x1f,0x02,0x04,0x00,0x00", "0x00,0x0e,0x0a,0x0e,0x04,0x0e,0x04,0x00",  //→ ♀
    "0x00,0x07,0x03,0x1d,0x14,0x1c,0x00,0x00", "0x00,0x00,0x0a,0x00,0x11,0x0e,0x00,0x00", "0x00,0x00,0x0a,0x00,0x0e,0x11,0x00,0x00",  //♂ smile sad
    "0x00,0x00,0x04,0x0a,0x11,0x1f,0x00,0x00", "0x00,0x00,0x1f,0x11,0x0a,0x04,0x00,0x00",  //△ ▽
    "0x00,0x0e,0x11,0x11,0x0a,0x1b,0x00,0x00", "0x00,0x11,0x0a,0x04,0x1f,0x04,0x04,0x00",  //Ω ￥
    "0x00,0x11,0x0a,0x04,0x0a,0x11,0x00,0x00", "0x00,0x00,0x01,0x02,0x14,0x08,0x00,0x00",  //Χ √
    "0x0e,0x11,0x17,0x19,0x19,0x17,0x11,0x0e", "0x00,0x06,0x07,0x05,0x0c,0x1c,0x08,0x00",  //© ♪
];

//预设字符
export const yf_lcd_preset_customChar = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('pChar_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    code += MIXLY_YF_PCUSTOMCHAR[dropdown_img_];
    code += '};\n';
    generator.definitions_['yf_char_' + dropdown_img_] = "byte " + 'yf_char_' + dropdown_img_ + "[]=" + code;
    return ['yf_char_' + dropdown_img_, generator.ORDER_ATOMIC];
}

//8X8 DOT MATRIX  -- 初始化
export const yf_dotMatrix_init = function (_, generator) {
    var SER = generator.valueToCode(this, 'PIN1', generator.ORDER_ATOMIC || '10');
    var RCK = generator.valueToCode(this, 'PIN2', generator.ORDER_ATOMIC || '11');
    var SRCK = generator.valueToCode(this, 'PIN3', generator.ORDER_ATOMIC || '12');
    generator.definitions_['include_TimerOne'] = '#include "TimerOne.h"';
    generator.definitions_['define_dotMatrix_SER'] = '#define SER ' + SER;
    generator.definitions_['define_dotMatrix_RCK'] = '#define RCK ' + RCK;
    generator.definitions_['define_dotMatrix_SRCK'] = '#define SRCK ' + SRCK;
    generator.setups_['setup_dotMatrix_SER'] = 'pinMode(SER,OUTPUT);';
    generator.setups_['setup_dotMatrix_RCK'] = 'pinMode(RCK,OUTPUT);';
    generator.setups_['setup_dotMatrix_SRCK'] = 'pinMode(SRCK,OUTPUT);\n';
    return '';
}

//8X8 DOT MATRIX  -- 显示
// export const yf_dotMatrix_display_singleDot = function() {
//   var dotArray = generator.valueToCode(this, 'dotArray', generator.ORDER_ATOMIC);
//   var time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC);
//   generator.definitions_['dotMatrix_display_Updata'] = 'void updateScreed(byte data[], unsigned long ReTime){\n'+
//     '  unsigned long startime = millis();\n'+
//     '  while (millis() - startime < ReTime){\n'+
//     '    for (int i = 0; i < 8; i++) {\n'+
//     '      byte col = B1 << i;\n'+
//     '      digitalWrite(RCK, LOW);\n'+
//     '      shiftOut(SER, SRCK, LSBFIRST, ~col); \n'+
//     '      shiftOut(SER, SRCK, LSBFIRST, data[i]); \n'+
//     '      digitalWrite(RCK, HIGH);\n'+
//     '    }\n'+
//     '  }\n'+
//     '}';
//   var code = 'updateScreed('+dotArray+','+time+');\n'
//   return code;
// }

//显示 - 自定义 单点
export const yf_dotMatrix_display_singleDot = function (_, generator) {
    var col = generator.valueToCode(this, 'col', generator.ORDER_ATOMIC);
    var row = generator.valueToCode(this, 'row', generator.ORDER_ATOMIC);
    var time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC);
    var funcName = 'updateScreed_sigleDot';
    var funcCode = 'void ' + funcName + '(int col, int row, unsigned long ReTime) {\n'
        + '  byte a[8][8] = {};\n'
        + '  byte b[8] = {};\n'
        + '  for (int i = 0; i < 8; i++) {\n'
        + '    for (int j = 0; j < 8; j++) {\n'
        + '      a[i][j] = (col == j + 1 && row == i + 1) ? 1 : 0;\n'
        + '      b[i] += a[i][j] << 7 - j;\n'
        + '    }\n'
        + '  }\n'
        + '  unsigned long startime = millis();\n'
        + '  while (millis() - startime < ReTime){\n'
        + '    for (int i = 0; i < 8; i++) {\n'
        + '      byte col = B1 << 7 - i;\n'
        + '      digitalWrite(RCK, LOW);\n'
        + '      shiftOut(SER, SRCK, LSBFIRST, ~col); \n'
        + '      shiftOut(SER, SRCK, LSBFIRST, b[i]); \n'
        + '      digitalWrite(RCK, HIGH);\n'
        + '    }\n'
        + '  }\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;
    var code = funcName + '(' + col + ',' + row + ',' + time + ');\n'
    return code;
}

//显示 - 自定义 单点
// export const dotArray_CustomArrayMath = function() {
//   var col = generator.valueToCode(this, 'col', generator.ORDER_ATOMIC);
//   var row = generator.valueToCode(this, 'row', generator.ORDER_ATOMIC);
//   var a = new Array();
//   for (var i = 0; i < 8; i++) {
//   // for (var i = 7; i >= 0; i--) {
//     a[i] = new Array();
//     for (var j = 0; j < 8; j++) {
//       a[i][j] = (col == j+1&&row == i+1) ? 1 : 0;
//     }
//   }
//   var code = '{';
//   for (var i = 0; i < 8; i++) {
//     var tmp = "";
//     for (var j = 0; j < 8; j++) {
//       tmp += a[7-i][j];
//     }
//     tmp = (parseInt(tmp, 2)).toString(16)
//     if (tmp.length == 1) tmp = "0" + tmp;
//     code += '0x' + tmp + ((i != 7) ? ',' : '');
//   }
//   code += '};\n';
//   var varName = "sigledDot"+col+row;
//   generator.definitions_['dotMatrix_display_'+varName] = "byte " + varName + "[]=" + code;
//   return [varName, generator.ORDER_ATOMIC];
// }

//8X8 DOT MATRIX  -- 显示
export const yf_dotMatrix_display = function (_, generator) {
    var dotArray = generator.valueToCode(this, 'dotArray', generator.ORDER_ATOMIC);
    var time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC);
    generator.definitions_['dotMatrix_display_Updata'] = 'void updateScreed(byte data[], unsigned long ReTime){\n' +
        '  unsigned long startime = millis();\n' +
        '  while (millis() - startime < ReTime){\n' +
        '    for (int i = 0; i < 8; i++) {\n' +
        '      byte col = B1 << i;\n' +
        '      digitalWrite(RCK, LOW);\n' +
        '      shiftOut(SER, SRCK, LSBFIRST, ~col); \n' +
        '      shiftOut(SER, SRCK, LSBFIRST, data[i]); \n' +
        '      digitalWrite(RCK, HIGH);\n' +
        '    }\n' +
        '  }\n' +
        '}';
    var code = 'updateScreed(' + dotArray + ',' + time + ');\n'
    return code;
}

//显示 - 自定义图案数组
export const dotArray_CustomArrayGraph = function (_, generator) {
    var varName = this.getFieldValue('VAR');
    var a = new Array();
    for (let i = 0; i < 8; i++) {
        // for (var i = 7; i >= 0; i--) {
        a[i] = new Array();
        for (let j = 0; j < 8; j++) {
            a[i][j] = (this.getFieldValue('a' + j + i) == 'TRUE') ? 1 : 0;
        }
    }
    var code = '{';
    for (let i = 0; i < 8; i++) {
        var tmp = "";
        for (let j = 0; j < 8; j++) {
            tmp += a[7 - i][j];
        }
        tmp = (parseInt(tmp, 2)).toString(16)
        if (tmp.length == 1) tmp = "0" + tmp;
        code += '0x' + tmp + ((i != 7) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_[varName] = "byte " + varName + "[]=" + code;
    return [varName, generator.ORDER_ATOMIC];
}

//8X8 DOT MATRIX  -- 显示 预设图案
export const yf_dotMatrix_preset_display = function (_, generator) {
    var presetDotArray = generator.valueToCode(this, 'presetDotArray', generator.ORDER_ATOMIC);
    var time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC);
    generator.definitions_['dotMatrix_display_Updata'] = 'void updateScreed(byte data[], unsigned long ReTime){\n' +
        '  unsigned long startime = millis();\n' +
        '  while (millis() - startime < ReTime){\n' +
        '    for (int i = 0; i < 8; i++) {\n' +
        '      byte col = B1 << i;\n' +
        '      digitalWrite(RCK, LOW);\n' +
        '      shiftOut(SER, SRCK, LSBFIRST, ~col); \n' +
        '      shiftOut(SER, SRCK, LSBFIRST, data[i]); \n' +
        '      digitalWrite(RCK, HIGH);\n' +
        '    }\n' +
        '  }\n' +
        '}';
    var code = 'updateScreed(' + presetDotArray + ',' + time + ');\n'
    return code;
}

//8X8 DOT MATRIX  -- 预设图案
export const yf_dotMatrix_preset_img_face = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('img_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    for (var i = 0; i < 15; i += 2) {
        code += '0x' + dropdown_img_.substr(i, 2) + ((i != 14) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_['define_yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    return ['yf_img_' + dropdown_img_, generator.ORDER_ATOMIC];
}

export const yf_dotMatrix_preset_img_dir = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('img_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    for (var i = 0; i < 15; i += 2) {
        code += '0x' + dropdown_img_.substr(i, 2) + ((i != 14) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_['define_yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    return ['yf_img_' + dropdown_img_, generator.ORDER_ATOMIC];
}

export const yf_dotMatrix_preset_img_music = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('img_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    for (var i = 0; i < 15; i += 2) {
        code += '0x' + dropdown_img_.substr(i, 2) + ((i != 14) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_['define_yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    return ['yf_img_' + dropdown_img_, generator.ORDER_ATOMIC];
}

export const yf_dotMatrix_preset_img_animal = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('img_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    for (var i = 0; i < 15; i += 2) {
        code += '0x' + dropdown_img_.substr(i, 2) + ((i != 14) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_['define_yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    return ['yf_img_' + dropdown_img_, generator.ORDER_ATOMIC];
}

export const yf_dotMatrix_preset_img_home = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('img_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    for (var i = 0; i < 15; i += 2) {
        code += '0x' + dropdown_img_.substr(i, 2) + ((i != 14) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_['define_yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    return ['yf_img_' + dropdown_img_, generator.ORDER_ATOMIC];
}

export const yf_dotMatrix_preset_img_office = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('img_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    for (var i = 0; i < 15; i += 2) {
        code += '0x' + dropdown_img_.substr(i, 2) + ((i != 14) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_['define_yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    return ['yf_img_' + dropdown_img_, generator.ORDER_ATOMIC];
}

export const yf_dotMatrix_preset_img_mathematics = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('img_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    for (var i = 0; i < 15; i += 2) {
        code += '0x' + dropdown_img_.substr(i, 2) + ((i != 14) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_['define_yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    return ['yf_img_' + dropdown_img_, generator.ORDER_ATOMIC];
}

export const yf_dotMatrix_preset_img_dice = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('img_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    for (var i = 0; i < 15; i += 2) {
        code += '0x' + dropdown_img_.substr(i, 2) + ((i != 14) ? ',' : '');
    }
    code += '};\n';
    // bug： 变量申明在使用变量后，提示变量未申明。
    // generator.definitions_['yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    generator.definitions_['define_yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    return ['yf_img_' + dropdown_img_, generator.ORDER_ATOMIC];
}

export const yf_dotMatrix_preset_img_battery = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('img_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    for (var i = 0; i < 15; i += 2) {
        code += '0x' + dropdown_img_.substr(i, 2) + ((i != 14) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_['define_yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    return ['yf_img_' + dropdown_img_, generator.ORDER_ATOMIC];
}

export const yf_dotMatrix_preset_img_weather = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('img_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    for (var i = 0; i < 15; i += 2) {
        code += '0x' + dropdown_img_.substr(i, 2) + ((i != 14) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_['define_yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    return ['yf_img_' + dropdown_img_, generator.ORDER_ATOMIC];
}

export const yf_dotMatrix_preset_img = function (_, generator) {
    var dropdown_img_ = this.getFieldValue('img_');
    var code = '"' + dropdown_img_ + '"';
    code = '{';
    for (var i = 0; i < 15; i += 2) {
        code += '0x' + dropdown_img_.substr(i, 2) + ((i != 14) ? ',' : '');
    }
    code += '};\n';
    generator.definitions_['define_yf_img_' + dropdown_img_] = "byte " + 'yf_img_' + dropdown_img_ + "[]=" + code;
    return ['yf_img_' + dropdown_img_, generator.ORDER_ATOMIC];
}


//TM1650 4 digital display  -- 数码管初始化
export const yf_4digitdisplay_init = function (_, generator) {
    var CLK = generator.valueToCode(this, 'PIN1', generator.ORDER_ATOMIC || '10');
    var DIO = generator.valueToCode(this, 'PIN2', generator.ORDER_ATOMIC || '11');
    generator.definitions_['include_TM1650'] = '#include "YFTM1650.h"';
    generator.definitions_['var_display_4display'] = 'YFTM1650 tm_4display(' + CLK + ',' + DIO + ');';
    generator.setups_['setup_tm1637_init'] = 'tm_4display.init();\n';
    return '';
}

// TM1650 4 digital display  -- 开关 清屏
export const yf_4digitdisplay_power = function () {
    var stat = this.getFieldValue("STAT");
    return 'tm_4display.' + stat + '();\n';
}

// TM1650 4 digital display  -- 显示字符串
export const yf_4digitdisplay_displayString = function (_, generator) {
    // var value = generator.valueToCode(this, 'VALUE', generator.ORDER_ATOMIC);
    var value = generator.valueToCode(this, 'VALUE', generator.ORDER_ATOMIC) || '""';
    return 'tm_4display.displayString(' + value + ');\n';
}

// TM1650 4 digital display  -- 显示数字
export const yf_4digitdisplay_displayNumber = function (_, generator) {
    var value = generator.valueToCode(this, 'VALUE', generator.ORDER_ATOMIC);
    return 'tm_4display.displayString(' + value + ');\n';
}

// TM1650 4 digital display  -- 小数点显示
export const yf_4digitdisplay_showDot = function (_, generator) {
    //var no=this.getFieldValue("NO");
    var dotNum = generator.valueToCode(this, 'DOTNUM', generator.ORDER_ASSIGNMENT) || '2';
    var stat = this.getFieldValue("STAT");
    return 'tm_4display.setDot(' + dotNum + '-1 ,' + stat + ');\n';
}

// TM1650 4 digital display  -- 设置亮度
export const yf_4digitdisplay_Brightness = function (_, generator) {
    var brightness = generator.valueToCode(this, 'brightness', generator.ORDER_ASSIGNMENT) || '8';
    var code = 'tm_4display.setBrightness(' + brightness + ');\n';
    return code;
}

// TM1650 4 digital display  -- 时钟模式
export const yf_4digitdisplay_Time = function (_, generator) {
    var time_hour = generator.valueToCode(this, 'time_hour', generator.ORDER_ASSIGNMENT);
    var time_minute = generator.valueToCode(this, 'time_minute', generator.ORDER_ASSIGNMENT);
    var time_second = this.getFieldValue('STAT');
    generator.definitions_['value_buf'] = 'char buf[5];';
    var code = 'snprintf_P(buf, sizeof(buf), PSTR("%02u%02u"), ' + time_hour + ', ' + time_minute + ');\n'
        + 'tm_4display.displayString(buf);\n';
    if (time_second == 'displaySEC_BLINK') {
        code += 'tm_4display.setDot(0,true);\n' + 'tm_4display.setDot(1,true);\n' + 'delay(500);\n' + 'tm_4display.setDot(0,false);\n' + 'tm_4display.setDot(1,false);\n' + 'delay(500);\n';
    } else if (time_second == 'displaySEC_ON') {
        code += 'tm_4display.setDot(0,true);\n' + 'tm_4display.setDot(1,true);\n';
    } else if (time_second == 'displaySEC_OFF') {
        code += 'tm_4display.setDot(0,false);\n' + 'tm_4display.setDot(1,false);\n';
    }
    return code;
}


/********************************************
TIME - 时钟模块
  - DS3231
  - DS1307
  - PCF8563
*********************************************/
// RTC real time clock  -- 设置时间
export const yf_rtc_SetTime = function (_, generator) {
    var rtc_w = this.getFieldValue('WHAT');
    var year = generator.valueToCode(this, 'YEAR', generator.ORDER_ATOMIC);
    var month = generator.valueToCode(this, 'MONTH', generator.ORDER_ATOMIC);
    var day = generator.valueToCode(this, 'DAY', generator.ORDER_ATOMIC);
    var hour = generator.valueToCode(this, 'HOUR', generator.ORDER_ATOMIC);
    var minute = generator.valueToCode(this, 'MINUTE', generator.ORDER_ATOMIC);
    var second = generator.valueToCode(this, 'SECOND', generator.ORDER_ATOMIC);

    generator.definitions_['include_RTClib'] = '#include "RTClib.h"';
    generator.definitions_['include_daysOfTheWeek'] = 'char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};';
    generator.definitions_['var_declare_Rtc' + rtc_w] = 'RTC_' + rtc_w + ' Rtc;';
    generator.setups_['setup_Rtc.Begin'] = 'if (! Rtc.begin()) { \n' +
        '    while (1) delay(10); \n' +
        '  }';
    generator.setups_['setup_set_time'] = 'Rtc.adjust(DateTime(' + year + ', ' + month + ', '
        + day + ', ' + hour + ', ' + minute + ', ' + second + '));\n';
    if (rtc_w === 'PCF8563')
        generator.setups_['setup_rtc_pcf8563_start'] = 'Rtc.start();';
    return '';
}

// RTC real time clock  -- 设置当前时间
export const yf_rtc_SetTime2 = function (_, generator) {
    var rtc_w = this.getFieldValue('WHAT');
    generator.definitions_['include_RTClib'] = '#include "RTClib.h"';
    generator.definitions_['include_daysOfTheWeek'] = 'char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};';
    generator.definitions_['var_declare_Rtc' + rtc_w] = 'RTC_' + rtc_w + ' Rtc;';
    generator.setups_['setup_Rtc.Begin'] = 'if (! Rtc.begin()) { \n' +
        '    while (1) delay(10); \n' +
        '  }';
    generator.setups_['setup_set_time'] = 'Rtc.adjust(DateTime(__DATE__, __TIME__));\n';
    if (rtc_w === 'PCF8563')
        generator.setups_['setup_rtc_pcf8563_start'] = 'Rtc.start();';
    return '';
}

// RTC real time clock  -- 获取
export const yf_rtc_GetTime = function (_, generator) {
    var rtc_w = this.getFieldValue('WHAT');
    generator.definitions_['include_RTClib'] = '#include "RTClib.h"';
    generator.definitions_['include_daysOfTheWeek'] = 'char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};';
    generator.definitions_['var_declare_Rtc' + rtc_w] = 'RTC_' + rtc_w + ' Rtc;';
    generator.setups_['setup_Rtc.Begin'] = 'if (! Rtc.begin()) { \n' +
        '    while (1) delay(10); \n' +
        '  }';
    if (rtc_w === 'PCF8563')
        generator.setups_['setup_rtc_pcf8563_start'] = 'Rtc.start();';

    var dropdown_type = this.getFieldValue('TIME_TYPE');
    var code = 'Rtc.now().' + dropdown_type + '()';
    return [code, generator.ORDER_ATOMIC];
}

/********************************************
Arduino Shield
*********************************************/

// Motor drive 模块 - drv8838
export const yf_motor_8838 = function (_, generator) {
    var DIR = generator.valueToCode(this, 'DIRPIN', generator.ORDER_ATOMIC || '4');
    var SP = generator.valueToCode(this, 'SPEEDPIN', generator.ORDER_ATOMIC || '5');

    var dropdown_dir = this.getFieldValue('DIR');
    var speed = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT) || '0';

    generator.definitions_['define_lego_m_dir' + DIR] = '#define DIRPIN' + DIR + ' ' + DIR;
    generator.definitions_['define_lego_m_spe' + SP] = '#define SPEPIN' + SP + ' ' + SP;
    generator.setups_['setup_output_lego_m_dir' + DIR] = 'pinMode(DIRPIN' + DIR + ', OUTPUT);';
    generator.setups_['setup_output_lego_m_spe' + SP] = 'pinMode(SPEPIN' + SP + ', OUTPUT);';
    // generator.setups_['setup_output_m2_dir'] = 'pinMode(M2DIRPIN, OUTPUT);';
    // generator.setups_['setup_output_m2_spe'] = 'pinMode(M2SPEPIN, OUTPUT);';
    generator.setups_['setup_output_lego_m_spe_low' + SP] = 'digitalWrite(SPEPIN' + SP + ', LOW);';
    // generator.setups_['setup_output_s_m2_spe'] = 'digitalWrite(M2SPEPIN, LOW);';
    var funcName = 'yfLEGOMotor_setMotor' + DIR + SP;
    var funcCode = 'void ' + funcName + '(int motorDir, int speed) {\n'
        + '  if(motorDir == 0) {\n'             // 反向
        + '    digitalWrite(DIRPIN' + DIR + ', LOW);\n'
        + '    analogWrite(SPEPIN' + SP + ', speed);\n'
        + '  } else if(motorDir == 1) {\n'      // 正向
        + '    digitalWrite(DIRPIN' + DIR + ', HIGH);\n'
        + '    analogWrite(SPEPIN' + SP + ', speed);\n'
        + '  } else if(motorDir == 2) {\n'      // 停止
        + '    analogWrite(SPEPIN' + SP + ', 0);\n'
        + '  }\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;
    var code = funcName + '(' + dropdown_dir + ',' + speed + ');\n';
    return code;
}

// Motor drive L298P模块
export const yf_l298p_motor = function (_, generator) {
    var dropdown_pin = this.getFieldValue('PIN');
    var dropdown_dir = this.getFieldValue('DIR');
    var speed = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT) || '0';
    generator.setups_['setup_output_4'] = 'pinMode(4, OUTPUT);';
    generator.setups_['setup_output_5'] = 'pinMode(5, OUTPUT);';
    generator.setups_['setup_output_6'] = 'pinMode(6, OUTPUT);';
    generator.setups_['setup_output_7'] = 'pinMode(7, OUTPUT);';
    generator.setups_['setup_output_w4'] = 'digitalWrite(4, LOW);';
    generator.setups_['setup_output_w5'] = 'digitalWrite(5, LOW);';
    generator.setups_['setup_output_w6'] = 'digitalWrite(6, LOW);';
    generator.setups_['setup_output_w7'] = 'digitalWrite(7, LOW);';
    var funcName = 'yf_setMotor';
    var funcCode = 'void ' + funcName + '(int motorId, int motorDir, int speed) {\n'
        + '  int speedPin, directionPin;\n'
        + '  if (motorId == 1) {         // motor 1\n'
        + '    speedPin = 5;\n'
        + '    directionPin = 4;\n'
        + '  } else if (motorId == 2) {  // motor 2\n'
        + '    speedPin = 6;\n'
        + '    directionPin = 7;\n'
        + '  } else {\n'
        + '    return;\n'
        + '  }\n'
        + '  if (speed == 0) {\n'                 // 停止
        + '    digitalWrite(speedPin, 0);\n'
        + '  } else {\n'
        + '    if(motorDir == 0) {\n'             // 反向
        + '      digitalWrite(directionPin, LOW);\n'
        + '      analogWrite(speedPin, speed);\n'
        + '    } else if(motorDir == 1) {\n'      // 正向
        + '      digitalWrite(directionPin, HIGH);\n'
        + '      analogWrite(speedPin, speed);\n'
        + '    }\n'
        + '  }\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;
    var code = funcName + '(' + dropdown_pin + ',' + dropdown_dir + ',' + speed + ');\n';
    return code;
}

export const yf_l298p_motor_stop = function (_, generator) {
    var dropdown_pin = this.getFieldValue('PIN');
    generator.setups_['setup_output_4'] = 'pinMode(4, OUTPUT);';
    generator.setups_['setup_output_5'] = 'pinMode(5, OUTPUT);';
    generator.setups_['setup_output_6'] = 'pinMode(6, OUTPUT);';
    generator.setups_['setup_output_7'] = 'pinMode(7, OUTPUT);';
    generator.setups_['setup_output_w4'] = 'digitalWrite(4, LOW);';
    generator.setups_['setup_output_w5'] = 'digitalWrite(5, LOW);';
    generator.setups_['setup_output_w6'] = 'digitalWrite(6, LOW);';
    generator.setups_['setup_output_w7'] = 'digitalWrite(7, LOW);';
    var funcName = 'yf_setMotor';
    var funcCode = 'void ' + funcName + '(int motorId, int motorDir, int speed) {\n'
        + '  int speedPin, directionPin;\n'
        + '  if (motorId == 1) {         // motor 1\n'
        + '    speedPin = 5;\n'
        + '    directionPin = 4;\n'
        + '  } else if (motorId == 2) {  // motor 2\n'
        + '    speedPin = 6;\n'
        + '    directionPin = 7;\n'
        + '  } else {\n'
        + '    return;\n'
        + '  }\n'
        + '  if (speed == 0) {\n'                 // 停止
        + '    digitalWrite(speedPin, 0);\n'
        + '  } else {\n'
        + '    if(motorDir == 0) {\n'             // 反向
        + '      digitalWrite(directionPin, LOW);\n'
        + '      analogWrite(speedPin, speed);\n'
        + '    } else if(motorDir == 1) {\n'      // 正向
        + '      digitalWrite(directionPin, HIGH);\n'
        + '      analogWrite(speedPin, speed);\n'
        + '    }\n'
        + '  }\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;
    var code = funcName + '(' + dropdown_pin + ',0,0); \n';
    return code;
}

// PM-R3多功能扩展板 TB6612
export const yf_pmr3_tb6612_motor = function (_, generator) {
    var dropdown_pin = this.getFieldValue('PIN');
    var dropdown_dir = this.getFieldValue('DIR');
    var speed = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT) || '0';
    generator.setups_['setup_output_4'] = 'pinMode(4, OUTPUT);';
    generator.setups_['setup_output_5'] = 'pinMode(5, OUTPUT);';
    generator.setups_['setup_output_6'] = 'pinMode(6, OUTPUT);';
    generator.setups_['setup_output_7'] = 'pinMode(7, OUTPUT);';
    generator.setups_['setup_output_w4'] = 'digitalWrite(4, LOW);';
    generator.setups_['setup_output_w5'] = 'digitalWrite(5, LOW);';
    generator.setups_['setup_output_w6'] = 'digitalWrite(6, LOW);';
    generator.setups_['setup_output_w7'] = 'digitalWrite(7, LOW);';
    var funcName = 'yf_setMotor';
    var funcCode = 'void ' + funcName + '(int motorId, int motorDir, int speed) {\n'
        + '  int speedPin, directionPin;\n'
        + '  if (motorId == 1) {         // motor 1\n'
        + '    speedPin = 5;\n'
        + '    directionPin = 4;\n'
        + '  } else if (motorId == 2) {  // motor 2\n'
        + '    speedPin = 6;\n'
        + '    directionPin = 7;\n'
        + '  } else {\n'
        + '    return;\n'
        + '  }\n'
        + '  if (speed == 0) {\n'                 // 停止
        + '    digitalWrite(speedPin, 0);\n'
        + '  } else {\n'
        + '    if(motorDir == 0) {\n'             // 反向
        + '      digitalWrite(directionPin, LOW);\n'
        + '      analogWrite(speedPin, speed);\n'
        + '    } else if(motorDir == 1) {\n'      // 正向
        + '      digitalWrite(directionPin, HIGH);\n'
        + '      analogWrite(speedPin, speed);\n'
        + '    }\n'
        + '  }\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;
    var code = funcName + '(' + dropdown_pin + ',' + dropdown_dir + ',' + speed + ');\n';
    return code;
}

export const yf_pmr3_tb6612_motor_stop = function (_, generator) {
    var dropdown_pin = this.getFieldValue('PIN');
    generator.setups_['setup_output_4'] = 'pinMode(4, OUTPUT);';
    generator.setups_['setup_output_5'] = 'pinMode(5, OUTPUT);';
    generator.setups_['setup_output_6'] = 'pinMode(6, OUTPUT);';
    generator.setups_['setup_output_7'] = 'pinMode(7, OUTPUT);';
    generator.setups_['setup_output_w4'] = 'digitalWrite(4, LOW);';
    generator.setups_['setup_output_w5'] = 'digitalWrite(5, LOW);';
    generator.setups_['setup_output_w6'] = 'digitalWrite(6, LOW);';
    generator.setups_['setup_output_w7'] = 'digitalWrite(7, LOW);';
    var funcName = 'yf_setMotor';
    var funcCode = 'void ' + funcName + '(int motorId, int motorDir, int speed) {\n'
        + '  int speedPin, directionPin;\n'
        + '  if (motorId == 1) {         // motor 1\n'
        + '    speedPin = 5;\n'
        + '    directionPin = 4;\n'
        + '  } else if (motorId == 2) {  // motor 2\n'
        + '    speedPin = 6;\n'
        + '    directionPin = 7;\n'
        + '  } else {\n'
        + '    return;\n'
        + '  }\n'
        + '  if (speed == 0) {\n'                 // 停止
        + '    digitalWrite(speedPin, 0);\n'
        + '  } else {\n'
        + '    if(motorDir == 0) {\n'             // 反向
        + '      digitalWrite(directionPin, LOW);\n'
        + '      analogWrite(speedPin, speed);\n'
        + '    } else if(motorDir == 1) {\n'      // 正向
        + '      digitalWrite(directionPin, HIGH);\n'
        + '      analogWrite(speedPin, speed);\n'
        + '    }\n'
        + '  }\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;
    var code = funcName + '(' + dropdown_pin + ',0,0); \n';
    return code;
}

export const yf_pmr3_tb6612_buzzer = function (_, generator) {
    var dropdown_pin = '12';
    var fre = generator.valueToCode(this, 'FREQUENCY', generator.ORDER_ASSIGNMENT) || '0';
    var dur = generator.valueToCode(this, 'DURATION', generator.ORDER_ASSIGNMENT) || '0';
    generator.setups_['setup_output_' + dropdown_pin] = 'pinMode(' + dropdown_pin + ', OUTPUT);';
    var code = "tone(" + dropdown_pin + "," + fre + "," + dur + ");\n";
    return code;
}

// i2c Motor drive 模块
export const yf_i2cmotor = function (_, generator) {
    generator.definitions_['define_MotorDriver_lib'] = '#include "MotorDriver.h"';
    generator.definitions_['define_MotorDriver_type'] = '#define MOTORTYPE YF_IIC_RZ';
    generator.definitions_['define_SerialDebug'] = 'uint8_t SerialDebug = -1;';
    generator.definitions_['define_motorDriveObject'] = 'MotorDriver i2cMotor = MotorDriver(MOTORTYPE);';

    generator.setups_['setup_init_MotorDriver'] = 'i2cMotor.begin();';
    generator.setups_['setup_init_MotorDriver_config'] = 'i2cMotor.motorConfig(1, -1, 1, -1);';
    generator.setups_['setup_ServoPWMFreq'] = 'i2cMotor.setPWMFreq(50);';
    return '';
}

// i2c Motor drive 模块 驱动单电机
export const yf_i2cmotor_setSingleMotor = function (_, generator) {
    var mx = this.getFieldValue('MX');
    var mxval = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT) || '0';
    var code = 'i2cMotor.setSingleMotor(' + mx + ',' + mxval + ');\n';
    return code;
}

// I2C电机驱动 驱动4路电机
export const yf_i2cmotor_setAllMotor = function (_, generator) {
    var mxval = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT) || '0';
    var code = 'i2cMotor.setAllMotor(' + mxval + ');\n';
    return code;
}

// I2C电机驱动 分别驱动4路电机
export const yf_i2cmotor_setMotor = function (_, generator) {
    var mxval = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT) || '0';
    var mxval2 = generator.valueToCode(this, 'speed2', generator.ORDER_ASSIGNMENT) || '0';
    var mxval3 = generator.valueToCode(this, 'speed3', generator.ORDER_ASSIGNMENT) || '0';
    var mxval4 = generator.valueToCode(this, 'speed4', generator.ORDER_ASSIGNMENT) || '0';
    var code = 'i2cMotor.setMotor(' + mxval + ',' + mxval2 + ',' + mxval3 + ',' + mxval4 + ');\n';
    return code;
}

// i2c Motor drive 模块 停止电机
export const yf_i2cmotor_stopMotor = function () {
    var mx = this.getFieldValue('MX');
    var code = 'i2cMotor.stopMotor(' + mx + ');\n';
    return code;
}

// i2c Motor drive 模块 驱动舵机
export const yf_i2cmotor_servoWrite = function (_, generator) {
    var channl = this.getFieldValue('CHANNL');
    var angle = generator.valueToCode(this, 'angle', generator.ORDER_ASSIGNMENT) || '0';
    var code = 'i2cMotor.servoWrite(' + channl + ',' + angle + ');\n';
    return code;
}



// i2c 1508 Motor drive 模块
export const yf_i2c1508motor = function (_, generator) {
    generator.definitions_['define_MDIIC1508_lib'] = '#include "MDIIC1508.h"';
    generator.definitions_['define_MDIIC1508Object'] = 'MDIIC1508 md_iic1508;';

    generator.setups_['setup_init_MDIIC1508O'] = 'if (md_iic1508.begin(MDIIC1508_ADDRESS) == false) {\n    while (1) ;  // If we fail to communicate, loop forever.\n  }';
    return '';
}

// i2c 1508 Motor drive 模块 驱动单电机
export const yf_i2c1508motor_setSingleMotor = function (_, generator) {
    var mx = this.getFieldValue('MX');
    var mxval = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT) || '0';
    var code = 'md_iic1508.setMotor(' + mx + ',' + mxval + ');\n';
    return code;
}

// i2c 1508 Motor drive 模块 分别驱动4路电机
export const yf_i2c1508motor_setMotor = function (_, generator) {
    var mxval = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT) || '0';
    var mxval2 = generator.valueToCode(this, 'speed2', generator.ORDER_ASSIGNMENT) || '0';
    var mxval3 = generator.valueToCode(this, 'speed3', generator.ORDER_ASSIGNMENT) || '0';
    var mxval4 = generator.valueToCode(this, 'speed4', generator.ORDER_ASSIGNMENT) || '0';
    var code = 'md_iic1508.setMotor(' + mxval + ',' + mxval2 + ',' + mxval3 + ',' + mxval4 + ');\n';
    return code;
}

// i2c 1508 Motor drive 模块 停止电机
export const yf_i2c1508motor_stopMotor = function () {
    var mx = this.getFieldValue('MX');
    var code = 'md_iic1508.stopMotor(' + mx + ');\n';
    return code;
}

/********************************************
Legoduino, Legoduino Pro 8838 电机驱动模块
*********************************************/
// Motor drive 模块 - drv8838
export const yf_legoduino_motor_8838 = function (_, generator) {
    var dropdown_dir_A = this.getFieldValue('DIRA');
    var dropdown_dir_B = this.getFieldValue('DIRB');
    var speed_A = generator.valueToCode(this, 'speedA', generator.ORDER_ASSIGNMENT) || '0';
    var speed_B = generator.valueToCode(this, 'speedB', generator.ORDER_ASSIGNMENT) || '0';
    generator.definitions_['define_mA_dir'] = '#define MADIRPIN 4';
    generator.definitions_['define_mA_spe'] = '#define MASPEPIN 5';
    generator.definitions_['define_mB_dir'] = '#define MBDIRPIN 7';
    generator.definitions_['define_mB_spe'] = '#define MBSPEPIN 6';
    generator.setups_['setup_output_mA_dir'] = 'pinMode(MADIRPIN, OUTPUT);';
    generator.setups_['setup_output_mA_spe'] = 'pinMode(MASPEPIN, OUTPUT);';
    generator.setups_['setup_output_mB_dir'] = 'pinMode(MBDIRPIN, OUTPUT);';
    generator.setups_['setup_output_mB_spe'] = 'pinMode(MBSPEPIN, OUTPUT);';
    generator.setups_['setup_output_s_mA_spe'] = 'digitalWrite(MASPEPIN, LOW);';
    generator.setups_['setup_output_s_mB_spe'] = 'digitalWrite(MBSPEPIN, LOW);';
    var funcName = 'yf_legoduino_setMotor';
    var funcCode = 'void ' + funcName + '(int motorADir, int speedA, int motorBDir, int speedB) {\n'
        + '  if (speedA == 0) {\n'                 // A停止
        + '    digitalWrite(MASPEPIN, 0);\n'
        + '  } else {\n'
        + '    if(motorADir == 0) {\n'             // A反向
        + '      digitalWrite(MADIRPIN, LOW);\n'
        + '      analogWrite(MASPEPIN, speedA);\n'
        + '    } else if(motorADir == 1) {\n'      // A正向
        + '      digitalWrite(MADIRPIN, HIGH);\n'
        + '      analogWrite(MASPEPIN, speedA);\n'
        + '    }\n'
        + '  }\n'
        + '  if (speedB == 0) {\n'                 // B停止
        + '    digitalWrite(MBSPEPIN, 0);\n'
        + '  } else {\n'
        + '    if(motorBDir == 0) {\n'             // B反向
        + '      digitalWrite(MBDIRPIN, LOW);\n'
        + '      analogWrite(MBSPEPIN, speedB);\n'
        + '    } else if(motorBDir == 1) {\n'      // B正向
        + '      digitalWrite(MBDIRPIN, HIGH);\n'
        + '      analogWrite(MBSPEPIN, speedB);\n'
        + '    }\n'
        + '  }\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;
    var code = funcName + '(' + dropdown_dir_A + ',' + speed_A + ',' + dropdown_dir_B + ',' + speed_B + ');\n';
    return code;
}

/********************************************
遥控 - 红外遥控 、 PS2-手柄遥控
*********************************************/
//红外接收模块
export const yf_ir_recv = function (_, generator) {
    var variable = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
    generator.definitions_['var_declare' + variable] = 'long ' + variable + ';';
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var branch = generator.statementToCode(this, 'DO');
    var branch2 = generator.statementToCode(this, 'DO2');
    generator.definitions_['define_ir_recv'] = '#include <IRremote.h>';
    //generator.definitions_['var_declare'+varName] = 'long '+varName+';\n';
    generator.definitions_['var_ir_recv' + dropdown_pin] = 'IRrecv irrecv_' + dropdown_pin + '(' + dropdown_pin + ');\ndecode_results results_' + dropdown_pin + ';\n';
    generator.setups_['setup_ir_recv_' + dropdown_pin] = 'irrecv_' + dropdown_pin + '.enableIRIn();';
    var code = "if (irrecv_" + dropdown_pin + ".decode(&results_" + dropdown_pin + ")) {\n"
    code += '  ' + variable + '=results_' + dropdown_pin + '.value;\n';
    code += '  String type="UNKNOWN";\n';
    ////////////////////////////////////////////////////////////////
    code += '  String typelist[14]={"UNKNOWN", "NEC", "SONY", "RC5", "RC6", "DISH", "SHARP", "PANASONIC", "JVC", "SANYO", "MITSUBISHI", "SAMSUNG", "LG", "WHYNTER"};\n';
    code += '  if(results_' + dropdown_pin + '.decode_type>=1&&results_' + dropdown_pin + '.decode_type<=13){\n';
    code += '    type=typelist[results_' + dropdown_pin + '.decode_type];\n'
    code += '  }\n';
    code += '  Serial.print("IR TYPE:"+type+"  ");\n';
    code += branch;
    code += '  irrecv_' + dropdown_pin + '.resume();\n'
    code += '} else {\n';
    code += branch2;
    code += '};\n';
    return code;
}

//红外mini遥控器2键值
export const yf_ir_val2 = function (_, generator) {
    // Numeric value.
    var code = (this.getFieldValue('VAL'));
    // -4.abs() returns -4 in Dart due to strange order of operation choices.
    // -4 is actually an operator and a number.  Reflect this in the order.
    var order = code < 0 ?
        generator.ORDER_UNARY_PREFIX : generator.ORDER_ATOMIC;
    return [code, order];
}

//红外mini遥控器键值
export const yf_ir_val = function (_, generator) {
    // Numeric value.
    var code = (this.getFieldValue('VAL'));
    // -4.abs() returns -4 in Dart due to strange order of operation choices.
    // -4 is actually an operator and a number.  Reflect this in the order.
    var order = code < 0 ?
        generator.ORDER_UNARY_PREFIX : generator.ORDER_ATOMIC;
    return [code, order];
}

//红外手柄式遥控器键值
export const yf_ir_handle_val = function (_, generator) {
    var code = (this.getFieldValue('VAL'));    // Numeric value.
    // -4.abs() returns -4 in Dart due to strange order of operation choices.
    // -4 is actually an operator and a number.  Reflect this in the order.
    var order = code < 0 ?
        generator.ORDER_UNARY_PREFIX : generator.ORDER_ATOMIC;
    return [code, order];
}

// PS2 Controller init
export const yf_ps2_init = function (_, generator) {
    var PS2_DAT = generator.valueToCode(this, 'PIN1', generator.ORDER_ATOMIC || '10');
    var PS2_CMD = generator.valueToCode(this, 'PIN2', generator.ORDER_ATOMIC || '11');
    var PS2_CS = generator.valueToCode(this, 'PIN3', generator.ORDER_ATOMIC || '12');
    var PS2_CLK = generator.valueToCode(this, 'PIN4', generator.ORDER_ATOMIC || '13');
    generator.definitions_['include_ps2'] = '#include "PS2X_lib.h"';
    generator.definitions_['define_ps2_dat'] = '#define PS2_DAT ' + PS2_DAT;
    generator.definitions_['define_ps2_cmd'] = '#define PS2_CMD ' + PS2_CMD;
    generator.definitions_['define_ps2_cs'] = '#define PS2_CS ' + PS2_CS;
    generator.definitions_['define_ps2_clk'] = '#define PS2_CLK ' + PS2_CLK;
    generator.definitions_['var_ps2x'] = 'PS2X ps2x;';
    generator.definitions_['var_int_error'] = 'int error;';
    generator.setups_['setup_init_ps2'] = 'error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_CS, PS2_DAT, true, true);\n';
    return '';

}

// PS2 Controller button
export const yf_ps2_btn = function (_, generator) {
    var PS2_BTN = generator.variableDB_.getName(this.getFieldValue('PS2_BTN'), Blockly.Variables.NAME_TYPE);
    var PS2_BTN_STATUS = generator.variableDB_.getName(this.getFieldValue('PS2_BTN_STATUS'), Blockly.Variables.NAME_TYPE);
    var code = 'ps2x.' + PS2_BTN_STATUS + '(' + PS2_BTN + ')';
    return [code, generator.ORDER_ATOMIC];
}

// PS2 Controller Rocker
export const yf_ps2_rocker = function (_, generator) {
    // var PS2_ROCKER_STATUS = this.getFieldValue('PS2_ROCKER_STATUS');
    var PS2_ROCKER_STATUS = generator.variableDB_.getName(this.getFieldValue('PS2_ROCKER_STATUS'), Blockly.Variables.NAME_TYPE);
    var code = 'ps2x.Analog(' + PS2_ROCKER_STATUS + ')';
    return [code, generator.ORDER_ATOMIC];
}

// PS2 Controller read analog value of the button  --- how hard you press the button
export const yf_ps2_a_btn = function (_, generator) {
    var PS2_A_BTN = this.getFieldValue('PS2_A_BTN');
    var code = 'ps2x.Analog(' + PS2_A_BTN + ')';
    return [code, generator.ORDER_ATOMIC];
}

// PS2 Controller read controller and setmotor
export const yf_ps2_readController_setMotor = function (_, generator) {
    var PS2_Motor1 = this.getFieldValue('MOTOR1');
    var PS2_Motor2 = generator.valueToCode(this, 'MOTOR2', generator.ORDER_ATOMIC || '0');
    var code = 'ps2x.read_gamepad(' + PS2_Motor1 + ',' + PS2_Motor2 + ');\n'
    // code += 'ps2x.reconfig_gamepad();\n'
    return code;
}

// PS2 Controller 判断是否异常
export const yf_ps2_isok = function () {
    var code = 'if(error == 1) {return;}\n'
    return code;
}


// I2C RFID射频模块 初始化
export const yf_rfid_iic_init = function (_, generator) {
    generator.definitions_['include_Wire'] = '#include <Wire.h>';
    generator.definitions_['include_MFRC522_I2C'] = '#include "MFRC522_I2C.h"';
    generator.definitions_['object_MFRC522_I2C'] = 'MFRC522 rfid(0X28, -1);';
    generator.definitions_['object_MFRC522_I2C_KEY'] = 'MFRC522::MIFARE_Key key;';
    generator.definitions_['object_MFRC522_I2C_STA'] = 'MFRC522::StatusCode status;';
    generator.setups_['setup_Wire_begin'] = 'Wire.begin();';
    generator.setups_['setup_init_MFRC522_I2C'] = 'rfid.PCD_Init();   // Init MFRC522\n';
    return '';
}

// I2C RFID射频模块 检测到卡
export const yf_rfid_iic_find_card = function (_, generator) {
    var code = '(rfid.PICC_IsNewCardPresent()==MFRC522::STATUS_OK && rfid.PICC_ReadCardSerial()==MFRC522::STATUS_OK)'
    return [code, generator.ORDER_ATOMIC];
}

// I2C RFID射频模块 判断卡ID
export const yf_rfid_iic_find_card_is = function (_, generator) {
    var uid_text = generator.valueToCode(this, 'UID_TEXT', generator.ORDER_ATOMIC) || '""';
    var code = '( rfid.IsCardUid(' + uid_text + ') )'
    return [code, generator.ORDER_ATOMIC];
}

// I2C RFID射频模块 获取ID
export const yf_rfid_iic_find_card_get_ID = function (_, generator) {
    var code = 'rfid.readUid()'
    return [code, generator.ORDER_ATOMIC];
}

// I2C RFID射频模块 打印卡片相关信息
export const yf_rfid_iic_Print = function () {
    var code = 'rfid.PICC_DumpToSerial(&(rfid.uid));\n'
    return code;
}


/********************************************
I2C IO 扩展
*********************************************/
// 输出
export const yf_i2cioext_digitalWrite = function (_, generator) {
    var i2c_addr = this.getFieldValue('I2CADDR');
    var i2c_iopin = this.getFieldValue('I2CIOPIN');
    var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC);

    generator.definitions_['include_aw9523'] = '#include <Adafruit_AW9523.h>';
    generator.definitions_['aw9523_' + i2c_addr] = 'Adafruit_AW9523 aw_' + i2c_addr + ';';

    generator.setups_['aw9523_' + i2c_addr + '.begin'] = 'aw_' + i2c_addr + '.begin(' + i2c_addr + ');';
    generator.setups_['setup_aw9523_' + i2c_addr + '_' + i2c_iopin + '.pinMode'] = 'aw_' + i2c_addr + '.pinMode(' + i2c_iopin + ', OUTPUT);';

    var code = 'aw_' + i2c_addr + '.digitalWrite(' + i2c_iopin + ',' + dropdown_stat + ');\n';
    return code;
}

// 输入
export const yf_i2cioext_digitalRead = function (_, generator) {
    var i2c_addr = this.getFieldValue('I2CADDR');
    var i2c_iopin = this.getFieldValue('I2CIOPIN');

    generator.definitions_['include_aw9523'] = '#include <Adafruit_AW9523.h>';
    generator.definitions_['aw9523_' + i2c_addr] = 'Adafruit_AW9523 aw_' + i2c_addr + ';';

    generator.setups_['aw9523_' + i2c_addr + '.begin'] = 'aw_' + i2c_addr + '.begin(' + i2c_addr + ');';
    generator.setups_['setup_aw9523_' + i2c_addr + '_' + i2c_iopin + '.pinMode'] = 'aw_' + i2c_addr + '.pinMode(' + i2c_iopin + ', INPUT);';

    var code = 'aw_' + i2c_addr + '.digitalRead(' + i2c_iopin + ')';
    return [code, generator.ORDER_ATOMIC];
}

/********************************************
IIC ADS1115 16位AD转换模块
*********************************************/
// 初始化模块 默认地址0x48
export const yf_i2c1115_Init = function (_, generator) {
    generator.definitions_['include_DFRobot_ADS1115'] = '#include <DFRobot_ADS1115.h>';
    generator.definitions_['DFRobot_ADS1115_0x48'] = 'DFRobot_ADS1115 yf_ads;';
    generator.setups_['DFRobot_ADS1115_0x48.begin'] = 'yf_ads.begin(0x48);';
    return '';
}

// 读取电压值（模拟量） 默认地址0x48
export const yf_i2c1115_readVoltage = function (_, generator) {
    var i2c_analogpin = this.getFieldValue('YF_I2CANALOGPIN');

    generator.definitions_['include_DFRobot_ADS1115'] = '#include <DFRobot_ADS1115.h>';
    generator.definitions_['DFRobot_ADS1115_0x48'] = 'DFRobot_ADS1115 yf_ads;';
    generator.setups_['DFRobot_ADS1115_0x48.begin'] = 'yf_ads.begin(0x48);';

    var code = 'yf_ads.readVoltage(' + i2c_analogpin + ')';
    return [code, generator.ORDER_ATOMIC];
}

/********************************************
指纹识别模块fingerprint recognition，串口通讯  波特率默认57600
*********************************************/
// 指纹识别模块 软件串口 初始化
export const yf_FPM_init_Software = function (_, generator) {
    // var board_type = Mixly.Boards.getType();  // 获取板型
    var dropdown_pin_rx = generator.valueToCode(this, 'PINRX', generator.ORDER_ATOMIC);
    var dropdown_pin_tx = generator.valueToCode(this, 'PINTX', generator.ORDER_ATOMIC);
    generator.definitions_['include_yfrobot_fpm383'] = '#include "yfrobot_fpm383.h"';
    // generator.definitions_['Object_YFROBOTFPM383_' + dropdown_pin_rx + '_' + dropdown_pin_tx] = 'YFROBOTFPM383 fpm(&yfSerial' + dropdown_pin_rx + '_' + dropdown_pin_tx + ');';
    generator.definitions_['Object_YFROBOTFPM383_' + dropdown_pin_rx + '_' + dropdown_pin_tx] = 'YFROBOTFPM383 fpm(' + dropdown_pin_rx + ',' + dropdown_pin_tx + ');//引脚RX TX';
    generator.setups_['setup_YFROBOTFPM383_init'] = 'fpm.getChipSN();';
    return "";
}

// 指纹识别模块  验证id
export const yf_FPM_identify = function (_, generator) {
    var identify_led_onoff = this.getFieldValue('STAT');
    var code = 'fpm.identify(' + identify_led_onoff + ')';
    return [code, generator.ORDER_ATOMIC];
}

// 指纹识别模块  注册id
export const yf_FPM_enroll = function (_, generator) {
    var id = generator.valueToCode(this, 'ID', generator.ORDER_ATOMIC);
    var enroll_time = generator.valueToCode(this, 'ETIME', generator.ORDER_ATOMIC);
    var code = 'fpm.enroll(' + id + ',' + enroll_time + ')';
    return [code, generator.ORDER_ATOMIC];
}

// 指纹识别模块  删除id
export const yf_FPM_delete = function (_, generator) {
    var id = generator.valueToCode(this, 'ID', generator.ORDER_ATOMIC);
    var code = 'fpm.deleteID(' + id + ')';
    return [code, generator.ORDER_ATOMIC];
}

// 指纹识别模块  清空指纹
export const yf_FPM_clear = function (_, generator) {
    // var id = generator.valueToCode(this, 'ID', generator.ORDER_ATOMIC);
    var code = 'fpm.empty()';
    return [code, generator.ORDER_ATOMIC];
}

// 指纹识别模块 查询注册指纹数量
export const yf_FPM_inquiry = function (_, generator) {
    // var id = generator.valueToCode(this, 'ID', generator.ORDER_ATOMIC);
    var code = 'fpm.inquiry()';
    return [code, generator.ORDER_ATOMIC];
}

/********************************************
编码器测速
*********************************************/
export const yf_encoder_motor = function (_, generator) {    
    var encoder_A = generator.valueToCode(this, 'ENCODER_A_PIN', generator.ORDER_ATOMIC);
    var encoder_B = generator.valueToCode(this, 'ENCODER_B_PIN', generator.ORDER_ATOMIC);
    
    var sampling_time = generator.valueToCode(this, 'ENCODER_SAMPLING_TIME', generator.ORDER_ATOMIC);
    var count_mode = this.getFieldValue('COUNT_MODE');
    
    generator.definitions_['defineEncoderValue_' + encoder_A] = 'volatile long encoder_'+ encoder_A +'_Value = 0; \n';
    generator.setups_['setup_encoder_a_' + encoder_A] = 'pinMode('+ encoder_A +', INPUT_PULLUP);';
    generator.setups_['setup_encoder_b_' + encoder_B] = 'pinMode('+ encoder_B +', INPUT_PULLUP);';
    generator.setups_['setup_attachInterrupt' + encoder_A] = 'attachInterrupt(digitalPinToInterrupt('+ encoder_A +'), yf_updateEncoder_t_'+ encoder_A +', RISING);';
    var funcName = 'yf_updateEncoder_t_'+ encoder_A;
    var funcCode = 'void ' + funcName + '() { //更新编码器值\n'
        + '  if (digitalRead('+ encoder_A +') == HIGH) {\n' 
        + '    encoder_'+ encoder_A +'_Value += (digitalRead('+ encoder_B +') == LOW) ? 1 : -1;\n'
        + '  } else { \n'
        + '    encoder_'+ encoder_A +'_Value += (digitalRead('+ encoder_B +') == LOW) ? -1 : 1;\n'
        + '  }\n'
        + '}\n';
    generator.definitions_[funcName] = funcCode;

    generator.definitions_['definePreviousMillis_' + encoder_A] = 'unsigned long previousMillis_'+ encoder_A +' = 0; // 记录上一次时间\n';
    generator.definitions_['defineSamplingTime_' + encoder_A] = 'int intervalTime_'+ encoder_A +' = '+ sampling_time +'; // 采样时间\n';
    var funcName_c = 'yf_countEncoder_t_'+ encoder_A;
    var funcCode_c = 'long ' + funcName_c + '() { //计算编码器值\n'
        + '  if ((unsigned long)(millis() -  previousMillis_'+ encoder_A +') >= intervalTime_'+ encoder_A +') {\n' 
        + '    detachInterrupt(digitalPinToInterrupt('+ encoder_A +')); //关闭中断\n'
        + '    long count_return = encoder_'+ encoder_A +'_Value;\n'
        + '    if(!' + count_mode + ') { encoder_'+ encoder_A +'_Value = 0 ; } // 清零操作\n'
        + '    previousMillis_'+ encoder_A +'= millis(); //更新上一次时间\n'
        + '    attachInterrupt(digitalPinToInterrupt('+ encoder_A +'), yf_updateEncoder_t_'+ encoder_A +', RISING); //开启中断\n'
        + '    return count_return;\n'
        + '  }\n'
        + '}\n';
    generator.definitions_[funcName_c] = funcCode_c;

    return [funcName_c + '()', generator.ORDER_ATOMIC];
}


export const yf_clear_encoder_count = function (_, generator) {    
    var encoder_A = generator.valueToCode(this, 'ENCODER_A_PIN', generator.ORDER_ATOMIC);
    var code = 'encoder_'+ encoder_A +'_Value = 0';
    return code;
}

/********************************************
4WD 麦轮小车
*********************************************/



/********************************************
more - 更多
*********************************************/